From d38ba22a3631afe2f4224ef061b777f9ba27c2a1 Mon Sep 17 00:00:00 2001
From: bcweaver <brianweaver@gmail.com>
Date: Tue, 23 Oct 2018 17:24:08 -0400
Subject: [PATCH] Removing unused 'group' package

---
 composer.json                                 |   1 -
 composer.lock                                 |  49 +-
 vendor/composer/installed.json                |  49 -
 web/modules/group/.gitignore                  |   2 -
 web/modules/group/LICENSE.txt                 | 339 -------
 web/modules/group/composer.json               |   6 -
 ...ield.storage.group_content.group_roles.yml |  19 -
 .../group/config/install/group.settings.yml   |   1 -
 .../optional/block.block.group_operations.yml |  21 -
 .../optional/views.view.group_members.yml     | 734 --------------
 .../group/config/schema/group.schema.yml      | 112 ---
 .../config/schema/group.views.schema.yml      |  46 -
 web/modules/group/css/toolbar.icons.theme.css |  10 -
 web/modules/group/group.api.php               |  35 -
 web/modules/group/group.group.permissions.yml |  16 -
 web/modules/group/group.info.yml              |  15 -
 web/modules/group/group.install               | 400 --------
 web/modules/group/group.libraries.yml         |  14 -
 web/modules/group/group.links.action.yml      |  38 -
 web/modules/group/group.links.contextual.yml  |  10 -
 web/modules/group/group.links.menu.yml        |  26 -
 web/modules/group/group.links.task.yml        |  98 --
 web/modules/group/group.module                | 496 ---------
 web/modules/group/group.permissions.yml       |  11 -
 web/modules/group/group.post_update.php       |  33 -
 web/modules/group/group.routing.yml           |  89 --
 web/modules/group/group.services.yml          | 102 --
 web/modules/group/group.tokens.inc            | 159 ---
 web/modules/group/group.views.inc             |  52 -
 .../group/images/icons/000000/toolbar.svg     |  52 -
 .../group/images/icons/787878/toolbar.svg     |  52 -
 web/modules/group/js/block.js                 |  53 -
 .../optional/views.view.group_nodes.yml       | 947 ------------------
 .../modules/gnode/gnode.group.permissions.yml |   3 -
 .../group/modules/gnode/gnode.info.yml        |  15 -
 web/modules/group/modules/gnode/gnode.install | 112 ---
 .../modules/gnode/gnode.links.action.yml      |  11 -
 web/modules/group/modules/gnode/gnode.module  | 292 ------
 .../group/modules/gnode/gnode.routing.yml     |   2 -
 .../src/Controller/GroupNodeController.php    | 114 ---
 .../Plugin/GroupContentEnabler/GroupNode.php  | 109 --
 .../GroupContentEnabler/GroupNodeDeriver.php  |  27 -
 .../src/Routing/GroupNodeRouteProvider.php    |  57 --
 .../src/Kernel/GroupNodeAccessRecordsTest.php |  97 --
 .../src/Kernel/GroupNodeAccessTestBase.php    | 157 ---
 .../tests/src/Kernel/GroupNodeGrantsTest.php  |  78 --
 .../modules/grolesync/grolesync.info.yml      |  15 -
 .../grolesync/grolesync.links.task.yml        |  12 -
 .../group/modules/grolesync/grolesync.module  |  86 --
 .../modules/grolesync/grolesync.routing.yml   |   7 -
 .../modules/grolesync/grolesync.services.yml  |   4 -
 .../grolesync/src/Form/GroupRoleSyncForm.php  |  60 --
 .../grolesync/src/GroupRoleSynchronizer.php   | 140 ---
 .../src/GroupRoleSynchronizerInterface.php    |  45 -
 .../group/src/Access/GroupAccessResult.php    |  77 --
 .../Access/GroupContentCreateAccessCheck.php  |  71 --
 .../GroupContentCreateAnyAccessCheck.php      |  75 --
 ...GroupContentCreateAnyEntityAccessCheck.php |  53 -
 .../GroupContentCreateEntityAccessCheck.php   |  52 -
 .../GroupInstalledContentAccessCheck.php      |  78 --
 .../src/Access/GroupMemberAccessCheck.php     |  50 -
 .../Access/GroupOwnsContentAccessCheck.php    |  61 --
 .../src/Access/GroupPermissionAccessCheck.php |  62 --
 .../src/Access/GroupPermissionHandler.php     | 296 ------
 .../GroupPermissionHandlerInterface.php       |  71 --
 .../group/src/Access/GroupPermissions.php     |  55 -
 .../Access/GroupPermissionsHashGenerator.php  | 150 ---
 ...GroupPermissionsHashGeneratorInterface.php |  26 -
 .../src/Annotation/GroupContentEnabler.php    | 109 --
 .../GroupContentTypeBreadcrumbBuilder.php     |  61 --
 .../src/Cache/Context/GroupCacheContext.php   |  52 -
 .../Cache/Context/GroupCacheContextBase.php   |  57 --
 .../GroupMembershipAudienceCacheContext.php   |  59 --
 .../Context/GroupMembershipCacheContext.php   |  61 --
 .../GroupMembershipCacheContextBase.php       |  88 --
 ...GroupMembershipPermissionsCacheContext.php |  95 --
 .../GroupMembershipRolesCacheContext.php      |  74 --
 .../Cache/Context/GroupTypeCacheContext.php   |  45 -
 .../group/src/Context/GroupRouteContext.php   |  56 --
 .../src/Context/GroupRouteContextTrait.php    |  65 --
 .../Controller/GroupMembershipController.php  | 107 --
 .../Access/GroupAccessControlHandler.php      |  44 -
 .../GroupContentAccessControlHandler.php      |  33 -
 .../GroupContentTypeAccessControlHandler.php  |  27 -
 .../Access/GroupRoleAccessControlHandler.php  |  36 -
 .../Access/GroupTypeAccessControlHandler.php  |  36 -
 .../Controller/GroupContentController.php     | 392 --------
 .../Controller/GroupContentListBuilder.php    | 163 ---
 .../Entity/Controller/GroupListBuilder.php    | 101 --
 .../Entity/Controller/GroupRoleController.php |  33 -
 .../Controller/GroupRoleListBuilder.php       | 126 ---
 .../Entity/Controller/GroupTypeController.php | 257 -----
 .../Controller/GroupTypeListBuilder.php       |  90 --
 .../Entity/Form/GroupContentDeleteForm.php    |  71 --
 .../src/Entity/Form/GroupContentForm.php      | 199 ----
 .../Form/GroupContentTypeDeleteForm.php       | 125 ---
 .../src/Entity/Form/GroupContentTypeForm.php  | 176 ----
 .../group/src/Entity/Form/GroupDeleteForm.php |  49 -
 .../group/src/Entity/Form/GroupForm.php       |  34 -
 .../src/Entity/Form/GroupRoleDeleteForm.php   |  31 -
 .../group/src/Entity/Form/GroupRoleForm.php   | 165 ---
 .../src/Entity/Form/GroupTypeDeleteForm.php   |  67 --
 .../group/src/Entity/Form/GroupTypeForm.php   | 171 ----
 web/modules/group/src/Entity/Group.php        | 361 -------
 web/modules/group/src/Entity/GroupContent.php | 370 -------
 .../src/Entity/GroupContentInterface.php      |  66 --
 .../group/src/Entity/GroupContentType.php     | 247 -----
 .../src/Entity/GroupContentTypeInterface.php  |  79 --
 .../group/src/Entity/GroupInterface.php       | 153 ---
 web/modules/group/src/Entity/GroupRole.php    | 334 ------
 .../group/src/Entity/GroupRoleInterface.php   | 188 ----
 web/modules/group/src/Entity/GroupType.php    | 321 ------
 .../group/src/Entity/GroupTypeInterface.php   | 181 ----
 .../Routing/GroupContentRouteProvider.php     | 217 ----
 .../Entity/Routing/GroupRoleRouteProvider.php |  60 --
 .../src/Entity/Routing/GroupRouteProvider.php |  65 --
 .../Entity/Routing/GroupTypeRouteProvider.php |  25 -
 .../Entity/Storage/GroupContentStorage.php    |  32 -
 .../Storage/GroupContentStorageInterface.php  |  29 -
 .../Storage/GroupContentTypeStorage.php       | 121 ---
 .../GroupContentTypeStorageInterface.php      |  63 --
 .../src/Entity/Storage/GroupRoleStorage.php   | 107 --
 .../Storage/GroupRoleStorageInterface.php     |  30 -
 .../Entity/ViewBuilder/GroupViewBuilder.php   |  30 -
 .../Entity/Views/GroupContentViewsData.php    | 120 ---
 .../group/src/Entity/Views/GroupViewsData.php |  37 -
 web/modules/group/src/Form/GroupJoinForm.php  |  32 -
 web/modules/group/src/Form/GroupLeaveForm.php |  28 -
 .../group/src/Form/GroupPermissionsForm.php   | 259 -----
 .../Form/GroupPermissionsRoleSpecificForm.php |  63 --
 .../Form/GroupPermissionsTypeSpecificForm.php | 115 ---
 .../group/src/Form/GroupSettingsForm.php      |  61 --
 web/modules/group/src/GroupMembership.php     | 120 ---
 .../group/src/GroupMembershipLoader.php       | 125 ---
 .../src/GroupMembershipLoaderInterface.php    |  55 -
 .../src/Plugin/Block/GroupOperationsBlock.php |  70 --
 .../group/src/Plugin/Condition/GroupType.php  | 134 ---
 .../GroupTypeRoleSelection.php                |  36 -
 .../GroupContentEnabler/GroupMembership.php   | 232 -----
 .../src/Plugin/GroupContentEnablerBase.php    | 552 ----------
 .../Plugin/GroupContentEnablerCollection.php  |  37 -
 .../Plugin/GroupContentEnablerInterface.php   | 297 ------
 .../src/Plugin/GroupContentEnablerManager.php | 421 --------
 .../GroupContentEnablerManagerInterface.php   | 123 ---
 .../Menu/LocalAction/WithDestination.php      |  69 --
 .../Constraint/GroupContentCardinality.php    |  36 -
 .../GroupContentCardinalityValidator.php      | 143 ---
 .../Plugin/views/access/GroupPermission.php   | 180 ----
 .../src/Plugin/views/argument/GroupId.php     |  66 --
 .../views/argument_default/GroupIdFromUrl.php |  86 --
 .../relationship/GroupContentToEntity.php     |  38 -
 .../relationship/GroupContentToEntityBase.php | 196 ----
 .../GroupContentToEntityReverse.php           |  35 -
 .../relationship/GroupToGroupContent.php      | 193 ----
 .../GroupContentUninstallValidator.php        |  87 --
 .../src/Routing/GroupAdminRouteSubscriber.php |  44 -
 .../GroupContentUninstallValidator.php        |  90 --
 .../group/templates/group-content.html.twig   |  54 -
 web/modules/group/templates/group.html.twig   |  56 --
 ....content_type.default-group_membership.yml |  15 -
 .../install/group.role.default-custom.yml     |  15 -
 .../install/group.role.default-member.yml     |  15 -
 .../install/group.role.default-outsider.yml   |  15 -
 .../config/install/group.type.default.yml     |   6 -
 .../group_test_config.info.yml                |  12 -
 .../sync/group.type.import.yml                |   6 -
 .../group_test_plugin.info.yml                |  15 -
 .../GroupContentEnabler/UserAsContent.php     |  21 -
 .../group_test_views.info.yml                 |  16 -
 ...t_group_content_to_entity_relationship.yml | 222 ----
 ...content_to_entity_reverse_relationship.yml | 239 -----
 .../views.view.test_group_id_argument.yml     | 202 ----
 ...st_group_to_group_content_relationship.yml | 221 ----
 .../src/Kernel/GroupContentCrudHookTest.php   |  45 -
 .../tests/src/Kernel/GroupCreatorTest.php     |  69 --
 .../tests/src/Kernel/GroupKernelTestBase.php  |  79 --
 .../group/tests/src/Kernel/GroupTest.php      |  53 -
 .../src/Kernel/GroupTokenReplaceTest.php      |  99 --
 .../tests/src/Kernel/GroupTypeCreateTest.php  |  57 --
 .../tests/src/Kernel/GroupTypeImportTest.php  |  65 --
 .../tests/src/Kernel/GroupTypeInstallTest.php |  47 -
 .../group/tests/src/Kernel/GroupTypeTest.php  |  92 --
 .../GroupContentToEntityRelationshipTest.php  | 157 ---
 ...ContentToEntityReverseRelationshipTest.php |  25 -
 .../src/Kernel/Views/GroupIdArgumentTest.php  |  95 --
 .../GroupToGroupContentRelationshipTest.php   | 165 ---
 186 files changed, 1 insertion(+), 19498 deletions(-)
 delete mode 100644 web/modules/group/.gitignore
 delete mode 100644 web/modules/group/LICENSE.txt
 delete mode 100644 web/modules/group/composer.json
 delete mode 100644 web/modules/group/config/install/field.storage.group_content.group_roles.yml
 delete mode 100644 web/modules/group/config/install/group.settings.yml
 delete mode 100644 web/modules/group/config/optional/block.block.group_operations.yml
 delete mode 100644 web/modules/group/config/optional/views.view.group_members.yml
 delete mode 100644 web/modules/group/config/schema/group.schema.yml
 delete mode 100644 web/modules/group/config/schema/group.views.schema.yml
 delete mode 100644 web/modules/group/css/toolbar.icons.theme.css
 delete mode 100644 web/modules/group/group.api.php
 delete mode 100644 web/modules/group/group.group.permissions.yml
 delete mode 100644 web/modules/group/group.info.yml
 delete mode 100644 web/modules/group/group.install
 delete mode 100644 web/modules/group/group.libraries.yml
 delete mode 100644 web/modules/group/group.links.action.yml
 delete mode 100644 web/modules/group/group.links.contextual.yml
 delete mode 100644 web/modules/group/group.links.menu.yml
 delete mode 100644 web/modules/group/group.links.task.yml
 delete mode 100644 web/modules/group/group.module
 delete mode 100644 web/modules/group/group.permissions.yml
 delete mode 100644 web/modules/group/group.post_update.php
 delete mode 100644 web/modules/group/group.routing.yml
 delete mode 100644 web/modules/group/group.services.yml
 delete mode 100644 web/modules/group/group.tokens.inc
 delete mode 100644 web/modules/group/group.views.inc
 delete mode 100644 web/modules/group/images/icons/000000/toolbar.svg
 delete mode 100644 web/modules/group/images/icons/787878/toolbar.svg
 delete mode 100644 web/modules/group/js/block.js
 delete mode 100644 web/modules/group/modules/gnode/config/optional/views.view.group_nodes.yml
 delete mode 100644 web/modules/group/modules/gnode/gnode.group.permissions.yml
 delete mode 100644 web/modules/group/modules/gnode/gnode.info.yml
 delete mode 100644 web/modules/group/modules/gnode/gnode.install
 delete mode 100644 web/modules/group/modules/gnode/gnode.links.action.yml
 delete mode 100644 web/modules/group/modules/gnode/gnode.module
 delete mode 100644 web/modules/group/modules/gnode/gnode.routing.yml
 delete mode 100644 web/modules/group/modules/gnode/src/Controller/GroupNodeController.php
 delete mode 100644 web/modules/group/modules/gnode/src/Plugin/GroupContentEnabler/GroupNode.php
 delete mode 100644 web/modules/group/modules/gnode/src/Plugin/GroupContentEnabler/GroupNodeDeriver.php
 delete mode 100644 web/modules/group/modules/gnode/src/Routing/GroupNodeRouteProvider.php
 delete mode 100644 web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeAccessRecordsTest.php
 delete mode 100644 web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeAccessTestBase.php
 delete mode 100644 web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeGrantsTest.php
 delete mode 100644 web/modules/group/modules/grolesync/grolesync.info.yml
 delete mode 100644 web/modules/group/modules/grolesync/grolesync.links.task.yml
 delete mode 100644 web/modules/group/modules/grolesync/grolesync.module
 delete mode 100644 web/modules/group/modules/grolesync/grolesync.routing.yml
 delete mode 100644 web/modules/group/modules/grolesync/grolesync.services.yml
 delete mode 100644 web/modules/group/modules/grolesync/src/Form/GroupRoleSyncForm.php
 delete mode 100644 web/modules/group/modules/grolesync/src/GroupRoleSynchronizer.php
 delete mode 100644 web/modules/group/modules/grolesync/src/GroupRoleSynchronizerInterface.php
 delete mode 100644 web/modules/group/src/Access/GroupAccessResult.php
 delete mode 100644 web/modules/group/src/Access/GroupContentCreateAccessCheck.php
 delete mode 100644 web/modules/group/src/Access/GroupContentCreateAnyAccessCheck.php
 delete mode 100644 web/modules/group/src/Access/GroupContentCreateAnyEntityAccessCheck.php
 delete mode 100644 web/modules/group/src/Access/GroupContentCreateEntityAccessCheck.php
 delete mode 100644 web/modules/group/src/Access/GroupInstalledContentAccessCheck.php
 delete mode 100644 web/modules/group/src/Access/GroupMemberAccessCheck.php
 delete mode 100644 web/modules/group/src/Access/GroupOwnsContentAccessCheck.php
 delete mode 100644 web/modules/group/src/Access/GroupPermissionAccessCheck.php
 delete mode 100644 web/modules/group/src/Access/GroupPermissionHandler.php
 delete mode 100644 web/modules/group/src/Access/GroupPermissionHandlerInterface.php
 delete mode 100644 web/modules/group/src/Access/GroupPermissions.php
 delete mode 100644 web/modules/group/src/Access/GroupPermissionsHashGenerator.php
 delete mode 100644 web/modules/group/src/Access/GroupPermissionsHashGeneratorInterface.php
 delete mode 100644 web/modules/group/src/Annotation/GroupContentEnabler.php
 delete mode 100644 web/modules/group/src/Breadcrumb/GroupContentTypeBreadcrumbBuilder.php
 delete mode 100644 web/modules/group/src/Cache/Context/GroupCacheContext.php
 delete mode 100644 web/modules/group/src/Cache/Context/GroupCacheContextBase.php
 delete mode 100644 web/modules/group/src/Cache/Context/GroupMembershipAudienceCacheContext.php
 delete mode 100644 web/modules/group/src/Cache/Context/GroupMembershipCacheContext.php
 delete mode 100644 web/modules/group/src/Cache/Context/GroupMembershipCacheContextBase.php
 delete mode 100644 web/modules/group/src/Cache/Context/GroupMembershipPermissionsCacheContext.php
 delete mode 100644 web/modules/group/src/Cache/Context/GroupMembershipRolesCacheContext.php
 delete mode 100644 web/modules/group/src/Cache/Context/GroupTypeCacheContext.php
 delete mode 100644 web/modules/group/src/Context/GroupRouteContext.php
 delete mode 100644 web/modules/group/src/Context/GroupRouteContextTrait.php
 delete mode 100644 web/modules/group/src/Controller/GroupMembershipController.php
 delete mode 100644 web/modules/group/src/Entity/Access/GroupAccessControlHandler.php
 delete mode 100644 web/modules/group/src/Entity/Access/GroupContentAccessControlHandler.php
 delete mode 100644 web/modules/group/src/Entity/Access/GroupContentTypeAccessControlHandler.php
 delete mode 100644 web/modules/group/src/Entity/Access/GroupRoleAccessControlHandler.php
 delete mode 100644 web/modules/group/src/Entity/Access/GroupTypeAccessControlHandler.php
 delete mode 100644 web/modules/group/src/Entity/Controller/GroupContentController.php
 delete mode 100644 web/modules/group/src/Entity/Controller/GroupContentListBuilder.php
 delete mode 100644 web/modules/group/src/Entity/Controller/GroupListBuilder.php
 delete mode 100644 web/modules/group/src/Entity/Controller/GroupRoleController.php
 delete mode 100644 web/modules/group/src/Entity/Controller/GroupRoleListBuilder.php
 delete mode 100644 web/modules/group/src/Entity/Controller/GroupTypeController.php
 delete mode 100644 web/modules/group/src/Entity/Controller/GroupTypeListBuilder.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupContentDeleteForm.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupContentForm.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupContentTypeDeleteForm.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupContentTypeForm.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupDeleteForm.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupForm.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupRoleDeleteForm.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupRoleForm.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupTypeDeleteForm.php
 delete mode 100644 web/modules/group/src/Entity/Form/GroupTypeForm.php
 delete mode 100644 web/modules/group/src/Entity/Group.php
 delete mode 100644 web/modules/group/src/Entity/GroupContent.php
 delete mode 100644 web/modules/group/src/Entity/GroupContentInterface.php
 delete mode 100644 web/modules/group/src/Entity/GroupContentType.php
 delete mode 100644 web/modules/group/src/Entity/GroupContentTypeInterface.php
 delete mode 100644 web/modules/group/src/Entity/GroupInterface.php
 delete mode 100644 web/modules/group/src/Entity/GroupRole.php
 delete mode 100644 web/modules/group/src/Entity/GroupRoleInterface.php
 delete mode 100644 web/modules/group/src/Entity/GroupType.php
 delete mode 100644 web/modules/group/src/Entity/GroupTypeInterface.php
 delete mode 100644 web/modules/group/src/Entity/Routing/GroupContentRouteProvider.php
 delete mode 100644 web/modules/group/src/Entity/Routing/GroupRoleRouteProvider.php
 delete mode 100644 web/modules/group/src/Entity/Routing/GroupRouteProvider.php
 delete mode 100644 web/modules/group/src/Entity/Routing/GroupTypeRouteProvider.php
 delete mode 100644 web/modules/group/src/Entity/Storage/GroupContentStorage.php
 delete mode 100644 web/modules/group/src/Entity/Storage/GroupContentStorageInterface.php
 delete mode 100644 web/modules/group/src/Entity/Storage/GroupContentTypeStorage.php
 delete mode 100644 web/modules/group/src/Entity/Storage/GroupContentTypeStorageInterface.php
 delete mode 100644 web/modules/group/src/Entity/Storage/GroupRoleStorage.php
 delete mode 100644 web/modules/group/src/Entity/Storage/GroupRoleStorageInterface.php
 delete mode 100644 web/modules/group/src/Entity/ViewBuilder/GroupViewBuilder.php
 delete mode 100644 web/modules/group/src/Entity/Views/GroupContentViewsData.php
 delete mode 100644 web/modules/group/src/Entity/Views/GroupViewsData.php
 delete mode 100644 web/modules/group/src/Form/GroupJoinForm.php
 delete mode 100644 web/modules/group/src/Form/GroupLeaveForm.php
 delete mode 100644 web/modules/group/src/Form/GroupPermissionsForm.php
 delete mode 100644 web/modules/group/src/Form/GroupPermissionsRoleSpecificForm.php
 delete mode 100644 web/modules/group/src/Form/GroupPermissionsTypeSpecificForm.php
 delete mode 100644 web/modules/group/src/Form/GroupSettingsForm.php
 delete mode 100644 web/modules/group/src/GroupMembership.php
 delete mode 100644 web/modules/group/src/GroupMembershipLoader.php
 delete mode 100644 web/modules/group/src/GroupMembershipLoaderInterface.php
 delete mode 100644 web/modules/group/src/Plugin/Block/GroupOperationsBlock.php
 delete mode 100644 web/modules/group/src/Plugin/Condition/GroupType.php
 delete mode 100644 web/modules/group/src/Plugin/EntityReferenceSelection/GroupTypeRoleSelection.php
 delete mode 100644 web/modules/group/src/Plugin/GroupContentEnabler/GroupMembership.php
 delete mode 100644 web/modules/group/src/Plugin/GroupContentEnablerBase.php
 delete mode 100644 web/modules/group/src/Plugin/GroupContentEnablerCollection.php
 delete mode 100644 web/modules/group/src/Plugin/GroupContentEnablerInterface.php
 delete mode 100644 web/modules/group/src/Plugin/GroupContentEnablerManager.php
 delete mode 100644 web/modules/group/src/Plugin/GroupContentEnablerManagerInterface.php
 delete mode 100644 web/modules/group/src/Plugin/Menu/LocalAction/WithDestination.php
 delete mode 100644 web/modules/group/src/Plugin/Validation/Constraint/GroupContentCardinality.php
 delete mode 100644 web/modules/group/src/Plugin/Validation/Constraint/GroupContentCardinalityValidator.php
 delete mode 100644 web/modules/group/src/Plugin/views/access/GroupPermission.php
 delete mode 100644 web/modules/group/src/Plugin/views/argument/GroupId.php
 delete mode 100644 web/modules/group/src/Plugin/views/argument_default/GroupIdFromUrl.php
 delete mode 100644 web/modules/group/src/Plugin/views/relationship/GroupContentToEntity.php
 delete mode 100644 web/modules/group/src/Plugin/views/relationship/GroupContentToEntityBase.php
 delete mode 100644 web/modules/group/src/Plugin/views/relationship/GroupContentToEntityReverse.php
 delete mode 100644 web/modules/group/src/Plugin/views/relationship/GroupToGroupContent.php
 delete mode 100644 web/modules/group/src/ProxyClass/UninstallValidator/GroupContentUninstallValidator.php
 delete mode 100644 web/modules/group/src/Routing/GroupAdminRouteSubscriber.php
 delete mode 100644 web/modules/group/src/UninstallValidator/GroupContentUninstallValidator.php
 delete mode 100644 web/modules/group/templates/group-content.html.twig
 delete mode 100644 web/modules/group/templates/group.html.twig
 delete mode 100644 web/modules/group/tests/modules/group_test_config/config/install/group.content_type.default-group_membership.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_config/config/install/group.role.default-custom.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_config/config/install/group.role.default-member.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_config/config/install/group.role.default-outsider.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_config/config/install/group.type.default.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_config/group_test_config.info.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_config/sync/group.type.import.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_plugin/group_test_plugin.info.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_plugin/src/Plugin/GroupContentEnabler/UserAsContent.php
 delete mode 100644 web/modules/group/tests/modules/group_test_views/group_test_views.info.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_content_to_entity_relationship.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_content_to_entity_reverse_relationship.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_id_argument.yml
 delete mode 100644 web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_to_group_content_relationship.yml
 delete mode 100644 web/modules/group/tests/src/Kernel/GroupContentCrudHookTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/GroupCreatorTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/GroupKernelTestBase.php
 delete mode 100644 web/modules/group/tests/src/Kernel/GroupTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/GroupTokenReplaceTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/GroupTypeCreateTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/GroupTypeImportTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/GroupTypeInstallTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/GroupTypeTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/Views/GroupContentToEntityRelationshipTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/Views/GroupContentToEntityReverseRelationshipTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/Views/GroupIdArgumentTest.php
 delete mode 100644 web/modules/group/tests/src/Kernel/Views/GroupToGroupContentRelationshipTest.php

diff --git a/composer.json b/composer.json
index 377d379cc2..91ecdfc98a 100644
--- a/composer.json
+++ b/composer.json
@@ -109,7 +109,6 @@
         "drupal/geocoder_autocomplete": "1.0",
         "drupal/geolocation": "1.10",
         "drupal/google_analytics": "2.2",
-        "drupal/group": "1.0-beta5",
         "drupal/honeypot": "^1.28",
         "drupal/image_popup": "1.1",
         "drupal/imce": "1.6",
diff --git a/composer.lock b/composer.lock
index 1a7fe73dd3..487c19ec08 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "89b4ef6f0837bccbb92d29d747661c46",
+    "content-hash": "793d8ae996392aed15f315c60a8d2431",
     "packages": [
         {
             "name": "alchemy/zippy",
@@ -4248,53 +4248,6 @@
                 "issues": "https://www.drupal.org/project/issues/google_analytics"
             }
         },
-        {
-            "name": "drupal/group",
-            "version": "1.0.0-beta5",
-            "source": {
-                "type": "git",
-                "url": "https://git.drupal.org/project/group",
-                "reference": "8.x-1.0-beta5"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/group-8.x-1.0-beta5.zip",
-                "reference": "8.x-1.0-beta5",
-                "shasum": "8584143f1e95d4eb29a89216906d68c11c6598c2"
-            },
-            "require": {
-                "drupal/core": "*"
-            },
-            "type": "drupal-module",
-            "extra": {
-                "branch-alias": {
-                    "dev-1.x": "1.x-dev"
-                },
-                "drupal": {
-                    "version": "8.x-1.0-beta5",
-                    "datestamp": "1496752442",
-                    "security-coverage": {
-                        "status": "not-covered",
-                        "message": "Beta releases are not covered by Drupal security advisories."
-                    }
-                }
-            },
-            "notification-url": "https://packages.drupal.org/8/downloads",
-            "license": [
-                "GPL-2.0+"
-            ],
-            "authors": [
-                {
-                    "name": "kristiaanvandeneynde",
-                    "homepage": "https://www.drupal.org/user/1345130"
-                }
-            ],
-            "description": "This module allows you to group users, content and other entities",
-            "homepage": "https://www.drupal.org/project/group",
-            "support": {
-                "source": "http://cgit.drupalcode.org/group"
-            }
-        },
         {
             "name": "drupal/honeypot",
             "version": "1.28.0",
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 1d0075297d..d52d8e5f6a 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -4377,55 +4377,6 @@
             "issues": "https://www.drupal.org/project/issues/google_analytics"
         }
     },
-    {
-        "name": "drupal/group",
-        "version": "1.0.0-beta5",
-        "version_normalized": "1.0.0.0-beta5",
-        "source": {
-            "type": "git",
-            "url": "https://git.drupal.org/project/group",
-            "reference": "8.x-1.0-beta5"
-        },
-        "dist": {
-            "type": "zip",
-            "url": "https://ftp.drupal.org/files/projects/group-8.x-1.0-beta5.zip",
-            "reference": "8.x-1.0-beta5",
-            "shasum": "8584143f1e95d4eb29a89216906d68c11c6598c2"
-        },
-        "require": {
-            "drupal/core": "*"
-        },
-        "type": "drupal-module",
-        "extra": {
-            "branch-alias": {
-                "dev-1.x": "1.x-dev"
-            },
-            "drupal": {
-                "version": "8.x-1.0-beta5",
-                "datestamp": "1496752442",
-                "security-coverage": {
-                    "status": "not-covered",
-                    "message": "Beta releases are not covered by Drupal security advisories."
-                }
-            }
-        },
-        "installation-source": "dist",
-        "notification-url": "https://packages.drupal.org/8/downloads",
-        "license": [
-            "GPL-2.0+"
-        ],
-        "authors": [
-            {
-                "name": "kristiaanvandeneynde",
-                "homepage": "https://www.drupal.org/user/1345130"
-            }
-        ],
-        "description": "This module allows you to group users, content and other entities",
-        "homepage": "https://www.drupal.org/project/group",
-        "support": {
-            "source": "http://cgit.drupalcode.org/group"
-        }
-    },
     {
         "name": "drupal/honeypot",
         "version": "1.28.0",
diff --git a/web/modules/group/.gitignore b/web/modules/group/.gitignore
deleted file mode 100644
index 5f27630538..0000000000
--- a/web/modules/group/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-# Ignore PhpStorm settings.
-/.idea
diff --git a/web/modules/group/LICENSE.txt b/web/modules/group/LICENSE.txt
deleted file mode 100644
index d159169d10..0000000000
--- a/web/modules/group/LICENSE.txt
+++ /dev/null
@@ -1,339 +0,0 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                            NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/web/modules/group/composer.json b/web/modules/group/composer.json
deleted file mode 100644
index 4d8e82a3c3..0000000000
--- a/web/modules/group/composer.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "name": "drupal/group",
-  "description": "This module allows you to group users, content and other entities",
-  "type": "drupal-module",
-  "license": "GPL-2.0+"
-}
diff --git a/web/modules/group/config/install/field.storage.group_content.group_roles.yml b/web/modules/group/config/install/field.storage.group_content.group_roles.yml
deleted file mode 100644
index c1b989a434..0000000000
--- a/web/modules/group/config/install/field.storage.group_content.group_roles.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-langcode: 'en'
-status: TRUE
-dependencies:
-  module:
-    - 'group'
-    - 'options'
-id: 'group_content.group_roles'
-field_name: 'group_roles'
-entity_type: 'group_content'
-type: 'entity_reference'
-settings:
-  target_type: 'group_role'
-module: 'core'
-locked: TRUE
-cardinality: -1
-translatable: FALSE
-indexes: {}
-persist_with_no_fields: TRUE
-custom_storage: FALSE
diff --git a/web/modules/group/config/install/group.settings.yml b/web/modules/group/config/install/group.settings.yml
deleted file mode 100644
index 4950007dc8..0000000000
--- a/web/modules/group/config/install/group.settings.yml
+++ /dev/null
@@ -1 +0,0 @@
-use_admin_theme: TRUE
diff --git a/web/modules/group/config/optional/block.block.group_operations.yml b/web/modules/group/config/optional/block.block.group_operations.yml
deleted file mode 100644
index d568ac1138..0000000000
--- a/web/modules/group/config/optional/block.block.group_operations.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-langcode: 'en'
-status: TRUE
-dependencies:
-  module:
-    - 'group'
-  theme:
-    - 'bartik'
-id: 'group_operations'
-theme: 'bartik'
-region: 'sidebar_first'
-weight: -20
-provider: NULL
-plugin: 'group_operations'
-settings:
-  id: 'group_operations'
-  label: 'Group operations'
-  provider: 'group'
-  label_display: 'visible'
-  context_mapping:
-    group: '@group.group_route_context:group'
-visibility: {}
diff --git a/web/modules/group/config/optional/views.view.group_members.yml b/web/modules/group/config/optional/views.view.group_members.yml
deleted file mode 100644
index be48c757aa..0000000000
--- a/web/modules/group/config/optional/views.view.group_members.yml
+++ /dev/null
@@ -1,734 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  config:
-    - field.storage.group_content.group_roles
-  module:
-    - group
-    - user
-id: group_members
-label: 'Group members'
-module: group
-description: ''
-tag: ''
-base_table: group_content_field_data
-base_field: id
-core: 8.x
-display:
-  default:
-    display_plugin: default
-    id: default
-    display_title: Master
-    position: 0
-    display_options:
-      access:
-        type: group_permission
-        options:
-          group_permission: 'administer members'
-      cache:
-        type: tag
-        options: {  }
-      query:
-        type: views_query
-        options:
-          disable_sql_rewrite: false
-          distinct: false
-          replica: false
-          query_comment: ''
-          query_tags: {  }
-      exposed_form:
-        type: basic
-        options:
-          submit_button: Apply
-          reset_button: false
-          reset_button_label: Reset
-          exposed_sorts_label: 'Sort by'
-          expose_sort_order: true
-          sort_asc_label: Asc
-          sort_desc_label: Desc
-      pager:
-        type: full
-        options:
-          items_per_page: 50
-          offset: 0
-          id: 0
-          total_pages: null
-          tags:
-            previous: ‹‹
-            next: ››
-            first: '« First'
-            last: 'Last »'
-          expose:
-            items_per_page: false
-            items_per_page_label: 'Items per page'
-            items_per_page_options: '5, 10, 25, 50'
-            items_per_page_options_all: false
-            items_per_page_options_all_label: '- All -'
-            offset: false
-            offset_label: Offset
-          quantity: 9
-      style:
-        type: table
-        options:
-          grouping: {  }
-          row_class: ''
-          default_row_class: true
-          override: true
-          sticky: true
-          caption: ''
-          summary: ''
-          description: ''
-          columns:
-            name: name
-            group_roles: group_roles
-            changed: changed
-            created: created
-            view_group_content: view_group_content
-            edit_group_content: edit_group_content
-            delete_group_content: delete_group_content
-            dropbutton: dropbutton
-          info:
-            name:
-              sortable: true
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            group_roles:
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            changed:
-              sortable: true
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            created:
-              sortable: true
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            view_group_content:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            edit_group_content:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            delete_group_content:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            dropbutton:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-          default: '-1'
-          empty_table: true
-      row:
-        type: fields
-        options:
-          inline: {  }
-          separator: ''
-          hide_empty: false
-          default_field_elements: true
-      fields:
-        name:
-          id: name
-          table: users_field_data
-          field: name
-          relationship: gc__user
-          group_type: group
-          admin_label: ''
-          label: User
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: user_name
-          settings:
-            link_to_entity: true
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: user
-          entity_field: name
-          plugin_id: field
-        group_roles:
-          id: group_roles
-          table: group_content__group_roles
-          field: group_roles
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: Roles
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: '<div class="item-list"><ul><li>&lt;none&gt;</li></ul></div>'
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: target_id
-          type: entity_reference_label
-          settings:
-            link: false
-          group_column: target_id
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: ul
-          separator: ', '
-          field_api_classes: false
-          plugin_id: field
-        changed:
-          id: changed
-          table: group_content_field_data
-          field: changed
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: Updated
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: timestamp
-          settings:
-            date_format: short
-            custom_date_format: ''
-            timezone: ''
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: group_content
-          entity_field: changed
-          plugin_id: field
-        created:
-          id: created
-          table: group_content_field_data
-          field: created
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: Joined
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: timestamp
-          settings:
-            date_format: short
-            custom_date_format: ''
-            timezone: ''
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: group_content
-          entity_field: created
-          plugin_id: field
-        view_group_content:
-          id: view_group_content
-          table: group_content
-          field: view_group_content
-          relationship: none
-          group_type: group
-          admin_label: 'View member link'
-          label: ''
-          exclude: true
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: false
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          text: 'View member'
-          entity_type: group_content
-          plugin_id: entity_link
-        edit_group_content:
-          id: edit_group_content
-          table: group_content
-          field: edit_group_content
-          relationship: none
-          group_type: group
-          admin_label: 'Edit member link'
-          label: ''
-          exclude: true
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: false
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          text: 'Edit member'
-          entity_type: group_content
-          plugin_id: entity_link_edit
-        delete_group_content:
-          id: delete_group_content
-          table: group_content
-          field: delete_group_content
-          relationship: none
-          group_type: group
-          admin_label: 'Remove member link'
-          label: ''
-          exclude: true
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: false
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          text: 'Remove member'
-          entity_type: group_content
-          plugin_id: entity_link_delete
-        dropbutton:
-          id: dropbutton
-          table: views
-          field: dropbutton
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: Operations
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          fields:
-            view_group_content: view_group_content
-            edit_group_content: edit_group_content
-            delete_group_content: delete_group_content
-            name: '0'
-            group_roles: '0'
-            changed: '0'
-            created: '0'
-          destination: true
-          plugin_id: dropbutton
-      filters: {  }
-      sorts: {  }
-      header: {  }
-      footer: {  }
-      empty:
-        area_text_custom:
-          id: area_text_custom
-          table: views
-          field: area_text_custom
-          relationship: none
-          group_type: group
-          admin_label: ''
-          empty: true
-          tokenize: false
-          content: 'No members available.'
-          plugin_id: text_custom
-      relationships:
-        gc__user:
-          id: gc__user
-          table: group_content_field_data
-          field: gc__user
-          relationship: none
-          group_type: group
-          admin_label: 'Member account'
-          required: true
-          group_content_plugins:
-            group_membership: group_membership
-          entity_type: group_content
-          plugin_id: group_content_to_entity
-      arguments:
-        gid:
-          id: gid
-          table: group_content_field_data
-          field: gid
-          relationship: none
-          group_type: group
-          admin_label: ''
-          default_action: 'access denied'
-          exception:
-            value: all
-            title_enable: false
-            title: All
-          title_enable: true
-          title: '{{ arguments.gid|placeholder }} members'
-          default_argument_type: fixed
-          default_argument_options:
-            argument: ''
-          default_argument_skip_url: false
-          summary_options:
-            base_path: ''
-            count: true
-            items_per_page: 25
-            override: false
-          summary:
-            sort_order: asc
-            number_of_records: 0
-            format: default_summary
-          specify_validation: false
-          validate:
-            type: none
-            fail: 'not found'
-          validate_options: {  }
-          break_phrase: false
-          not: false
-          entity_type: group_content
-          entity_field: gid
-          plugin_id: numeric
-      display_extenders: {  }
-      title: Members
-    cache_metadata:
-      max-age: 0
-      contexts:
-        - group_membership.roles.permissions
-        - 'languages:language_content'
-        - 'languages:language_interface'
-        - url
-        - url.query_args
-      tags:
-        - 'config:field.storage.group_content.group_roles'
-  page_1:
-    display_plugin: page
-    id: page_1
-    display_title: Page
-    position: 1
-    display_options:
-      display_extenders: {  }
-      path: group/%group/members
-      menu:
-        type: tab
-        title: Members
-        description: ''
-        expanded: false
-        parent: ''
-        weight: 20
-        context: '0'
-        menu_name: main
-        enabled: true
-    cache_metadata:
-      max-age: 0
-      contexts:
-        - group_membership.roles.permissions
-        - 'languages:language_content'
-        - 'languages:language_interface'
-        - url
-        - url.query_args
-      tags:
-        - 'config:field.storage.group_content.group_roles'
diff --git a/web/modules/group/config/schema/group.schema.yml b/web/modules/group/config/schema/group.schema.yml
deleted file mode 100644
index f474f932dd..0000000000
--- a/web/modules/group/config/schema/group.schema.yml
+++ /dev/null
@@ -1,112 +0,0 @@
-# Schema for the configuration files of the group module.
-
-group.settings:
-  type: 'config_object'
-  label: 'Group settings'
-  mapping:
-    use_admin_theme:
-      type: 'boolean'
-      label: 'Use admin theme when editing or creating groups'
-
-group.type.*:
-  type: 'config_entity'
-  label: 'Group type'
-  mapping:
-    id:
-      type: 'string'
-      label: 'Machine-readable name'
-    label:
-      type: 'label'
-      label: 'Label'
-    description:
-      type: 'text'
-      label: 'Description'
-    creator_roles:
-      type: 'sequence'
-      label: 'Group creator roles'
-      sequence:
-        type: 'string'
-        label: 'Group role ID'
-
-group_content_enabler.config.group_cardinality:
-  type: 'integer'
-  label: 'Group cardinality'
-
-group_content_enabler.config.entity_cardinality:
-  type: 'integer'
-  label: 'Entity cardinality'
-
-group_content_enabler.config.use_creation_wizard:
-  type: 'boolean'
-  label: 'Use creation wizard'
-
-# Follows the pattern group.role.GROUP_TYPE_ID-GROUP_ROLE_ID.
-group.role.*:
-  type: 'config_entity'
-  label: 'Group role'
-  mapping:
-    id:
-      type: 'string'
-      label: 'Machine-readable name'
-    label:
-      type: 'label'
-      label: 'Label'
-    weight:
-      type: 'integer'
-      label: 'Weight'
-    internal:
-      type: 'boolean'
-      label: 'Group role is used internally'
-    audience:
-      type: 'string'
-      label: 'Audience'
-    group_type:
-      type: 'string'
-      label: 'Group type ID'
-    permissions_ui:
-      type: 'boolean'
-      label: 'Show this role in the default permissions UI'
-    permissions:
-      type: 'sequence'
-      label: 'Permissions'
-      sequence:
-        type: 'string'
-        label: 'Group permission'
-
-group_content_type:
-  type: 'config_entity'
-  label: 'Group content type'
-  mapping:
-    id:
-      type: 'string'
-      label: 'Machine-readable name'
-    label:
-      type: 'label'
-      label: 'Label'
-    description:
-      type: 'text'
-      label: 'Description'
-    group_type:
-      type: 'text'
-      label: 'Group type ID'
-    content_plugin:
-      type: 'text'
-      label: 'Group content plugin ID'
-    plugin_config:
-      type: 'sequence'
-      label: 'Plugin configuration'
-      sequence:
-        type: 'group_content_enabler.config.[%key]'
-
-# Follows the pattern group.content_type.GROUP_TYPE_ID-PLUGIN_ID.
-# Follows the pattern group.content_type.GROUP_TYPE_ID-PLUGIN_ID-DERIVATIVE_ID.
-group.content_type.*:
-  type: 'group_content_type'
-  label: 'Group content type'
-
-entity_reference_selection.group_type:group_role:
-  type: 'entity_reference_selection'
-  mapping:
-    group_type_id:
-      type: 'string'
-      label: 'The group type to check for available roles.'
diff --git a/web/modules/group/config/schema/group.views.schema.yml b/web/modules/group/config/schema/group.views.schema.yml
deleted file mode 100644
index 3942e60684..0000000000
--- a/web/modules/group/config/schema/group.views.schema.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-# Schema for the views plugins of the Group module.
-
-views.access.group_permission:
-  type: 'mapping'
-  label: 'Group permission'
-  mapping:
-    group_permission:
-      type: 'string'
-      label: 'Group permission'
-
-views.argument.group_id:
-  type: views_argument
-  label: 'Group ID'
-  mapping:
-    not:
-      type: boolean
-      label: 'Exclude'
-
-views.argument_default.group_id_from_url:
-  type: 'sequence'
-  label: 'Group ID from current route'
-  sequence:
-    type: 'string'
-    label: 'Group ID'
-
-views_relationship_with_group_plugin_filter:
-  type: 'views_relationship'
-  mapping:
-    group_content_plugins:
-      type: 'sequence'
-      label: 'Group content plugins'
-      sequence:
-        type: 'string'
-        label: 'Group content plugin ID'
-
-views.relationship.group_content_to_entity:
-  type: 'views_relationship_with_group_plugin_filter'
-  label: 'Group content to entity reference'
-
-views.relationship.group_content_to_entity_reverse:
-  type: 'views_relationship_with_group_plugin_filter'
-  label: 'Reverse group content to entity reference'
-
-views.relationship.group_to_group_content:
-  type: 'views_relationship_with_group_plugin_filter'
-  label: 'Group to group content'
diff --git a/web/modules/group/css/toolbar.icons.theme.css b/web/modules/group/css/toolbar.icons.theme.css
deleted file mode 100644
index ebc7bd1187..0000000000
--- a/web/modules/group/css/toolbar.icons.theme.css
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Main menu icons.
- */
-.toolbar-icon-system-admin-group:before {
-    background-image: url(../images/icons/787878/toolbar.svg);
-}
-.toolbar-icon-system-admin-group:active:before,
-.toolbar-icon-system-admin-group.is-active:before {
-    background-image: url(../images/icons/000000/toolbar.svg);
-}
diff --git a/web/modules/group/group.api.php b/web/modules/group/group.api.php
deleted file mode 100644
index 6b9ba4602f..0000000000
--- a/web/modules/group/group.api.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-/**
- * @file
- * Hooks specific to the Group module.
- */
-
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupInterface;
-
-/**
- * @addtogroup hooks
- * @{
- */
-
-/**
- * Alter the links for the group_operations block.
- *
- * @param array $operations
- *   A list of links to be set in an 'operations' element.
- * @param GroupInterface $group
- *   The group to alter the operations for.
- *
- * @see \Drupal\group\Plugin\Block\GroupOperationsBlock
- * @see \Drupal\Core\Render\Element\Dropbutton
- */
-function hook_group_operations_alter(array &$operations, GroupInterface $group) {
-  if ($group->label() == 'Hotel California') {
-    unset($operations['group-leave']);
-  }
-}
-
-/**
- * @} End of "addtogroup hooks".
- */
diff --git a/web/modules/group/group.group.permissions.yml b/web/modules/group/group.group.permissions.yml
deleted file mode 100644
index 64ce441fa8..0000000000
--- a/web/modules/group/group.group.permissions.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-administer group:
-  title: 'Administer group'
-  description: 'Administer the group, its content and members'
-  restrict access: TRUE
-view group:
-  title: 'View group'
-edit group:
-  title: 'Edit group'
-  description: 'Edit the group information'
-delete group:
-  title: 'Delete group'
-  description: 'Delete the group'
-access content overview:
-  title: 'Access related entities overview'
-  description: 'View all of the entity relations for the group'
-  warning: 'Warning: This can be rather technical and should only be granted to power users.'
diff --git a/web/modules/group/group.info.yml b/web/modules/group/group.info.yml
deleted file mode 100644
index 6d72d75404..0000000000
--- a/web/modules/group/group.info.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: 'Group'
-description: 'Allows you to group users, content and other entities'
-package: 'Group'
-type: 'module'
-# version: 1.0
-# core: '8.x'
-configure: 'group.settings'
-dependencies:
-  - 'options'
-
-# Information added by Drupal.org packaging script on 2017-02-20
-version: '8.x-1.0-beta5'
-core: '8.x'
-project: 'group'
-datestamp: 1487606183
diff --git a/web/modules/group/group.install b/web/modules/group/group.install
deleted file mode 100644
index 5cfb4df7de..0000000000
--- a/web/modules/group/group.install
+++ /dev/null
@@ -1,400 +0,0 @@
-<?php
-
-/**
- * @file
- * Install, update and uninstall functions for the group module.
- */
-
-use Drupal\group\Entity\GroupContent;
-use Drupal\Core\Config\ExtensionInstallStorage;
-use Drupal\Core\Config\InstallStorage;
-use Drupal\Core\Entity\EntityTypeListenerInterface;
-use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
-
-/**
- * Resave all GroupContent labels and remove orphaned entities.
- */
-function group_update_8001(&$sandbox) {
-  // Set up the batch by retrieving all of the group content IDs.
-  if (!isset($sandbox['progress'])) {
-    /** @var \Drupal\Core\Entity\EntityTypeManager $entity_type_manager */
-    $entity_type_manager = \Drupal::service('entity_type.manager');
-    $storage_handler = $entity_type_manager->getStorage('group_content');
-
-    $sandbox['ids'] = $storage_handler->getQuery()->execute();
-    $sandbox['max'] = count($sandbox['ids']);
-    $sandbox['progress'] = 0;
-  }
-
-  // Try to update 25 GroupContent entities at a time.
-  $ids = array_slice($sandbox['ids'], $sandbox['progress'], 25);
-
-  /** @var \Drupal\group\Entity\GroupContentInterface $group_content */
-  foreach (GroupContent::loadMultiple($ids) as $group_content) {
-    // Re-saving the GroupContent entities will properly set their label.
-    if ($group_content->getEntity()) {
-      $group_content->save();
-    }
-    // In early versions we did not delete GroupContent entities along with the
-    // entity they represent. Let's clean those up to avoid crashes for people
-    // who still have those floating around.
-    else {
-      $group_content->delete();
-    }
-
-    $sandbox['progress']++;
-  }
-
-  // Try to update the percentage but avoid division by zero.
-  $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
-
-  // Show a status update for the current progress.
-  return t("Updated the label for @progress out of @max group content entities.", ['@progress' => $sandbox['progress'], '@max' => $sandbox['max']]);
-}
-
-/**
- * Properly make Group and GroupContent translatable.
- */
-function group_update_8002() {
-  $container = \Drupal::getContainer();
-
-  /** @var \Drupal\Core\Database\Connection $database */
-  $database = $container->get('database');
-
-  /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager */
-  $entity_manager = $container->get('entity_type.manager');
-
-  /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager */
-  $field_manager = $container->get('entity_field.manager');
-
-  /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $schema_repository */
-  $schema_repository = $container->get('entity.last_installed_schema.repository');
-
-  // Before we start, we need to rebuild the entity type caches so we have the
-  // latest definitions in code available to us.
-  $entity_manager->clearCachedDefinitions();
-
-  foreach (['group', 'group_content'] as $entity_type_id) {
-    // Retrieve the storage handler class name for this entity type.
-    $storage_handler = $entity_manager->getHandler($entity_type_id, 'storage');
-
-    // Get the old entity type's field definitions from the key/value storage.
-    $old_field_def = $schema_repository->getLastInstalledFieldStorageDefinitions($entity_type_id);
-
-    // Get the old entity type definition from the key/value storage.
-    $old_entity_type = $schema_repository->getLastInstalledDefinition($entity_type_id);
-
-    // Get the new entity type definition from code.
-    $new_entity_type = $entity_manager->getDefinition($entity_type_id);
-
-    // Instantiate a storage handler for both entity type definitions. Please
-    // note we're cloning the old entity type definition because we are altering
-    // it further down this update function and don't want those changes to be
-    // reflected in the storage handler.
-    $old_storage = $entity_manager->createHandlerInstance($storage_handler, clone $old_entity_type);
-    $new_storage = $entity_manager->createHandlerInstance($storage_handler, $new_entity_type);
-
-    // We can't update the definition if the storage handler doesn't have the
-    // onEntityTypeCreate() method available to it.
-    if (!($new_storage instanceof EntityTypeListenerInterface)) {
-      // This should probably throw an exception, but we're in alpha.
-      return;
-    }
-
-    // We check for the SqlContentEntityStorage interface to make sure we do
-    // not run queries against a non-SQL backend. Seeing as our content entity
-    // types did not specify a storage backend, Drupal defaulted to SQL so all
-    // sites should be using that unless they swapped out the storage.
-    if (!($new_storage instanceof SqlContentEntityStorage && $old_storage instanceof SqlContentEntityStorage)) {
-      // This should probably throw an exception, but we're in alpha.
-      return;
-    }
-
-    // Get the table names for our data migration.
-    $base_table = $new_entity_type->getBaseTable();
-    $data_table = $base_table . '_field_data';
-    $temp_table = $base_table . '_data_to_migrate';
-
-    // First rename the base table to a temporary table.
-    $database->schema()->renameTable($base_table, $temp_table);
-
-    // Then recreate the base table and data table. This will also add the
-    // 'default_langcode' base field because we flagged our content entity types
-    // as translatable.
-    $new_storage->onEntityTypeCreate($new_entity_type);
-
-    // At this point the database structure should match what is defined in
-    // code. However, Drupal still thinks we are running the old definitions
-    // because it cached them in the key/value storage.
-    //
-    // We therefore need to adjust the old definition instead of just writing
-    // the new one to the key/value storage. By doing so, we ensure that other
-    // modules' changes to the definition are kept as well.
-    //
-    // Inform Drupal of the fact that our content entities are now translatable
-    // and have a data table.
-    $old_entity_type->set('translatable', TRUE);
-    $old_entity_type->set('data_table', $base_table . '_field_data');
-
-    // We had an additional property 'fieldable' which is now gone.
-    $additional = $old_entity_type->get('additional');
-    unset($additional['fieldable']);
-    $old_entity_type->set('additional', $additional);
-
-    // Now that we have added only our changes, we write the adjusted old entity
-    // type to the key/value storage as the new entity type.
-    $schema_repository->setLastInstalledDefinition($old_entity_type);
-
-    // As mentioned above, Drupal added a new 'default_langcode' field which we
-    // didn't have before. It's therefore safe to load the field's definition
-    // from code and write it to the key/value storage.
-    $field_definitions = $field_manager->getFieldStorageDefinitions($entity_type_id);
-    $schema_repository->setLastInstalledFieldStorageDefinition($field_definitions['default_langcode']);
-
-    // Now we just need to migrate the old data into the new table structure. We
-    // read the column names from both the old and new tables and select data
-    // from the old one into the new ones.
-    $temp_cols = $old_storage->getTableMapping($old_field_def)->getAllColumns($base_table);
-    $base_cols = $new_storage->getTableMapping()->getAllColumns($base_table);
-    $data_cols = $new_storage->getTableMapping()->getAllColumns($data_table);
-
-    // Get the columns the base and data table share with the old base table.
-    $base_shared = array_intersect($base_cols, $temp_cols);
-    $data_shared = array_intersect($data_cols, $temp_cols);
-
-    // Build subqueries for inserting old data into the new tables.
-    $base_query = $database->select($temp_table, 't')->fields('t', $base_shared);
-    $data_query = $database->select($temp_table, 't')->fields('t', $data_shared);
-
-    // We add a default value of 1 to the 'default_langcode' field.
-    $data_query->addExpression('1', 'default_langcode');
-
-    // Now we select all of the old data into the new tables.
-    $database->insert($base_table)->from($base_query)->execute();
-    $database->insert($data_table)->from($data_query)->execute();
-  }
-}
-
-/**
- * Update all group role entities to use the new audience property.
- */
-function group_update_8003() {
-  $config_factory = \Drupal::configFactory();
-
-  foreach ($config_factory->listAll('group.role.') as $group_role_config_name) {
-    $group_role = $config_factory->getEditable($group_role_config_name);
-
-    // Figure out what audience the role is for based on role ID.
-    list(, $group_role_id) = explode('-', $group_role->get('id'), 2);
-    switch ($group_role_id) {
-      case 'anonymous':
-        $audience = 'anonymous';
-        break;
-
-      case 'outsider':
-        $audience = 'outsider';
-        break;
-
-      default:
-        $audience = 'member';
-    }
-
-    $group_role->set('audience', $audience);
-    $group_role->save(TRUE);
-  }
-}
-
-/**
- * Update all group role entities to use the new permissions_ui property.
- */
-function group_update_8004() {
-  $config_factory = \Drupal::configFactory();
-
-  foreach ($config_factory->listAll('group.role.') as $group_role_config_name) {
-    $group_role = $config_factory->getEditable($group_role_config_name);
-    $group_role->set('permissions_ui', TRUE);
-    $group_role->save(TRUE);
-  }
-}
-
-/**
- * Update all group types to fix some potentially broken plugin config.
- */
-function group_update_8005() {
-  $config_factory = \Drupal::configFactory();
-
-  foreach ($config_factory->listAll('group.type.') as $group_type_config_name) {
-    $group_type = $config_factory->getEditable($group_type_config_name);
-    list(,,$group_type_id) = explode('.', $group_type_config_name);
-
-    // Make sure the group type ID is set in the plugin config.
-    $plugins = $group_type->get('content');
-    foreach ($plugins as $plugin_id => $config) {
-      $group_type->set("content.$plugin_id.group_type", $group_type_id);
-    }
-
-    $group_type->save(TRUE);
-  }
-}
-
-/**
- * Move all plugin config from group types to group content types.
- */
-function group_update_8006() {
-  $config_factory = \Drupal::configFactory();
-  $plugin_config = [];
-
-  // Get the configuration from every group type.
-  foreach ($config_factory->listAll('group.type.') as $group_type_config_name) {
-    $group_type = $config_factory->getEditable($group_type_config_name);
-    list(,,$group_type_id) = explode('.', $group_type_config_name);
-
-    // Store the group type's plugin configuration in an array.
-    $plugins = $group_type->get('content');
-    foreach ($plugins as $plugin_id => $config) {
-      $plugin_config[$group_type_id][$plugin_id] = $config['data'];
-    }
-
-    // Remove the plugin config from the group type altogether.
-    $group_type->clear('content');
-    $group_type->save(TRUE);
-  }
-
-  // Store the configuration on the group content types.
-  foreach ($config_factory->listAll('group.content_type.') as $group_content_type_config_name) {
-    $group_content_type = $config_factory->getEditable($group_content_type_config_name);
-    $group_type_id = $group_content_type->get('group_type');
-    $plugin_id = $group_content_type->get('content_plugin');
-    $group_content_type->set('plugin_config', $plugin_config[$group_type_id][$plugin_id]);
-    $group_content_type->save(TRUE);
-  }
-}
-
-/**
- * Update the members view to use the argument provided title.
- */
-function group_update_8007() {
-  if (\Drupal::moduleHandler()->moduleExists('views')) {
-    $view = \Drupal::configFactory()->getEditable('views.view.group_members');
-    if (!$view->isNew()) {
-      $view->set('display.default.display_options.arguments.gid.title_enable', TRUE);
-      $view->set('display.default.display_options.arguments.gid.title', '{{ arguments.gid|placeholder }} members');
-      $view->save(TRUE);
-    }
-  }
-}
-
-/**
- * Make sure the views.view.group_members exists and fix broken copies.
- */
-function group_update_8008() {
-  $message = NULL;
-
-  $name = 'views.view.group_members';
-  $view = \Drupal::configFactory()->getEditable($name);
-
-  // Only update or insert the view if the Views module is enabled.
-  if (\Drupal::moduleHandler()->moduleExists('views')) {
-    $save_from_yaml = FALSE;
-
-    // If the view does not exist yet, we create it.
-    if ($view->isNew()) {
-      $save_from_yaml = TRUE;
-      $message = 'The view did not exist yet and has therefore been created.';
-    }
-    // We did not properly add the view in previous update functions, but did
-    // add keys to it, assuming the view existed. We should be able to find the
-    // broken views by checking for the absence of an ID.
-    elseif (!$view->get('id')) {
-      $save_from_yaml = TRUE;
-      $message = 'The view was broken by previous update hooks and has now been fixed.';
-    }
-
-    // If we flagged the view to be saved from the YAML definition, do so.
-    if ($save_from_yaml) {
-      // Get the storage for optional extension configuration.
-      $optional_storage = new ExtensionInstallStorage(
-        \Drupal::service('config.storage'),
-        InstallStorage::CONFIG_OPTIONAL_DIRECTORY
-      );
-
-      // Read the data from the YAML file and save it to the view.
-      $view->setData($optional_storage->read($name));
-      $view->save(TRUE);
-    }
-    else {
-      $message = 'The view was present and working as intended. Did nothing.';
-    }
-  }
-  // Otherwise delete the view if it exists in the storage.
-  elseif (!$view->isNew()) {
-    $view->delete();
-    $message = 'The view had been added even though the Views module is not installed. Removed the view.';
-  }
-
-  return $message;
-}
-
-/**
- * Add the 'creator_roles' property to all group types.
- */
-function group_update_8009() {
-  $config_factory = \Drupal::configFactory();
-
-  foreach ($config_factory->listAll('group.type.') as $group_type_config_name) {
-    $group_type = $config_factory->getEditable($group_type_config_name);
-    $group_type->set('creator_roles', []);
-    $group_type->save(TRUE);
-  }
-}
-
-/**
- * Change the path field to computed for group entities.
- */
-function group_update_8010() {
-  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
-  if ($entity_definition_update_manager->getEntityType('group')) {
-    // Computed field definitions are not tracked by the entity definition
-    // update manager, so remove them.
-    $storage_definition = $entity_definition_update_manager->getFieldStorageDefinition('path', 'group');
-    if ($storage_definition) {
-      $entity_definition_update_manager->uninstallFieldStorageDefinition($storage_definition);
-    }
-  }
-}
-
-/**
- * Remove the the 'info_text' config option from all group content types.
- */
-function group_update_8011() {
-  $config_factory = \Drupal::configFactory();
-
-  foreach ($config_factory->listAll('group.content_type.') as $group_content_type_config_name) {
-    $group_content_type = $config_factory->getEditable($group_content_type_config_name);
-    $group_content_type->clear('plugin_config.info_text');
-    $group_content_type->save(TRUE);
-  }
-}
-
-/**
- * Change 'edit' into 'update' in permission names.
- */
-function group_update_8012() {
-  $config_factory = \Drupal::configFactory();
-
-  foreach ($config_factory->listAll('group.role.') as $group_role_config_name) {
-    $group_role = $config_factory->getEditable($group_role_config_name);
-
-    // Replace 'edit any/own' with 'update any/own' in permission names.
-    $search = '%^edit (any|own) (\S+) (\S+)$%';
-    $replace = 'update $1 $2 $3';
-
-    $permissions = $group_role->get('permissions');
-    foreach ($permissions as &$permission) {
-      $permission = preg_replace($search, $replace, $permission);
-    }
-
-    $group_role->set('permissions', $permissions);
-    $group_role->save();
-  }
-}
diff --git a/web/modules/group/group.libraries.yml b/web/modules/group/group.libraries.yml
deleted file mode 100644
index 7acd4c646b..0000000000
--- a/web/modules/group/group.libraries.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-toolbar:
-  version: 'VERSION'
-  css:
-    theme:
-      css/toolbar.icons.theme.css: {}
-  dependencies:
-    - 'toolbar/toolbar'
-
-block:
-  version: 'VERSION'
-  js:
-    js/block.js: {}
-  dependencies:
-    - 'block/drupal.block'
diff --git a/web/modules/group/group.links.action.yml b/web/modules/group/group.links.action.yml
deleted file mode 100644
index 04f0ca88c7..0000000000
--- a/web/modules/group/group.links.action.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-group.add_group:
-  route_name: 'entity.group.add_page'
-  title: 'Add group'
-  appears_on:
-    - 'entity.group.collection'
-
-group.add_group_type:
-  route_name: 'entity.group_type.add_form'
-  title: 'Add group type'
-  appears_on:
-    - 'entity.group_type.collection'
-
-group.add_group_role:
-  route_name: 'entity.group_role.add_form'
-  title: 'Add group role'
-  appears_on:
-    - 'entity.group_role.collection'
-
-group.add_member:
-  route_name: 'entity.group_content.add_form'
-  route_parameters:
-    plugin_id: 'group_membership'
-  class: '\Drupal\group\Plugin\Menu\LocalAction\WithDestination'
-  title: 'Add member'
-  appears_on:
-    - 'view.group_members.page_1'
-
-group_content.add_page:
-  route_name: 'entity.group_content.add_page'
-  title: 'Relate existing entity to group'
-  appears_on:
-    - 'entity.group_content.collection'
-
-group_content.create_page:
-  route_name: 'entity.group_content.create_page'
-  title: 'Create new entity in group'
-  appears_on:
-    - 'entity.group_content.collection'
diff --git a/web/modules/group/group.links.contextual.yml b/web/modules/group/group.links.contextual.yml
deleted file mode 100644
index 4976b90728..0000000000
--- a/web/modules/group/group.links.contextual.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-entity.group.edit_form:
-  route_name: 'entity.group.edit_form'
-  group: 'group'
-  title: 'Edit'
-
-entity.group.delete_form:
-  route_name: 'entity.group.delete_form'
-  group: 'group'
-  title: 'Delete'
-  weight: 10
diff --git a/web/modules/group/group.links.menu.yml b/web/modules/group/group.links.menu.yml
deleted file mode 100644
index 6b66c3c9e6..0000000000
--- a/web/modules/group/group.links.menu.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-system.admin_group:
-  title: 'Groups'
-  description: 'Find and manage groups, group types and group settings.'
-  route_name: 'entity.group.collection'
-  parent: 'system.admin'
-  weight: 3
-
-entity.group.collection:
-  title: 'List'
-  description: 'Find and manage groups, group types and group settings.'
-  route_name: 'entity.group.collection'
-  parent: 'system.admin_group'
-
-entity.group_type.collection:
-  title: 'Group types'
-  description: 'Configure group types.'
-  route_name: 'entity.group_type.collection'
-  parent: 'system.admin_group'
-  weight: 5
-
-group.settings:
-  title: 'Settings'
-  description: 'Configure the general group module settings.'
-  route_name: 'group.settings'
-  parent: 'system.admin_group'
-  weight: 10
diff --git a/web/modules/group/group.links.task.yml b/web/modules/group/group.links.task.yml
deleted file mode 100644
index 0a9d472e09..0000000000
--- a/web/modules/group/group.links.task.yml
+++ /dev/null
@@ -1,98 +0,0 @@
-group.list:
-  title: 'List'
-  base_route: 'entity.group.collection'
-  route_name: 'entity.group.collection'
-
-group.types:
-  title: 'Group types'
-  base_route: 'entity.group.collection'
-  route_name: 'entity.group_type.collection'
-
-group.settings:
-  title: 'Settings'
-  base_route: 'entity.group.collection'
-  route_name: 'group.settings'
-
-group.view:
-  title: 'View'
-  base_route: 'entity.group.canonical'
-  route_name: 'entity.group.canonical'
-
-group.edit_form:
-  title: 'Edit'
-  base_route: 'entity.group.canonical'
-  route_name: 'entity.group.edit_form'
-
-group.delete_form:
-  title: 'Delete'
-  base_route: 'entity.group.canonical'
-  route_name: 'entity.group.delete_form'
-  weight: 10
-
-group.content:
-  title: 'Related entities'
-  base_route: 'entity.group.canonical'
-  route_name: 'entity.group_content.collection'
-  weight: 15
-
-group_type.edit_form:
-  title: 'Edit'
-  base_route: 'entity.group_type.edit_form'
-  route_name: 'entity.group_type.edit_form'
-
-group_type.permissions_form:
-  title: 'Permissions'
-  route_name: 'entity.group_type.permissions_form'
-  base_route: 'entity.group_type.edit_form'
-  weight: 15
-
-group_type.roles_list:
-  title: 'Roles'
-  route_name: 'entity.group_role.collection'
-  base_route: 'entity.group_type.edit_form'
-  weight: 20
-
-group_type.content_plugins:
-  title: 'Content'
-  base_route: 'entity.group_type.edit_form'
-  route_name: 'entity.group_type.content_plugins'
-  weight: 25
-
-group_content_type.edit_form:
-  title: 'Configure'
-  base_route: 'entity.group_content_type.edit_form'
-  route_name: 'entity.group_content_type.edit_form'
-
-group_role.edit_form:
-  title: 'Edit'
-  base_route: 'entity.group_role.edit_form'
-  route_name: 'entity.group_role.edit_form'
-
-group_role.delete_form:
-  title: 'Delete'
-  route_name: 'entity.group_role.delete_form'
-  base_route: 'entity.group_role.edit_form'
-  weight: 5
-
-group_role.permissions_form:
-  title: 'Permissions'
-  route_name: 'entity.group_role.permissions_form'
-  base_route: 'entity.group_role.edit_form'
-  weight: 10
-
-group_content.view:
-  title: 'View'
-  base_route: 'entity.group_content.canonical'
-  route_name: 'entity.group_content.canonical'
-
-group_content.edit:
-  title: 'Edit'
-  base_route: 'entity.group_content.canonical'
-  route_name: 'entity.group_content.edit_form'
-  weight: 5
-
-group_content.delete:
-  title: 'Remove'
-  base_route: 'entity.group_content.canonical'
-  route_name: 'entity.group_content.delete_form'
-  weight: 10
diff --git a/web/modules/group/group.module b/web/modules/group/group.module
deleted file mode 100644
index 2d156d1176..0000000000
--- a/web/modules/group/group.module
+++ /dev/null
@@ -1,496 +0,0 @@
-<?php
-
-/**
- * @file
- * Allows you to group users, content and other entities.
- */
-
-use Drupal\group\Entity\GroupContent;
-use Drupal\Core\Entity\ContentEntityForm;
-use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Render\Element;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Field\FieldDefinitionInterface;
-use Drupal\Core\Field\FieldItemListInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\Access\AccessResult;
-
-/**
- * Implements hook_help().
- */
-function group_help($route_name, RouteMatchInterface $route_match) {
-  switch ($route_name) {
-    case 'entity.group_type.content_plugins':
-      return '<p>' . t('Entities that can be added to this group type.') . '</p>';
-  }
-}
-
-/**
- * Implements hook_element_info_alter().
- */
-function group_element_info_alter(array &$types) {
-  // Attach our extra CSS for toolbar icons.
-  if (isset($types['toolbar'])) {
-    $types['toolbar']['#attached']['library'][] = 'group/toolbar';
-  }
-}
-
-/**
- * Implements hook_theme().
- */
-function group_theme() {
-  return [
-    'group' => [
-      'render element' => 'elements',
-    ],
-    'group_content' => [
-      'render element' => 'elements',
-    ],
-  ];
-}
-
-/**
- * Implements hook_theme_suggestions_HOOK().
- */
-function group_theme_suggestions_group(array $variables) {
-  $suggestions = [];
-
-  /** @var \Drupal\group\Entity\GroupInterface $group */
-  $group = $variables['elements']['#group'];
-  $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
-
-  $suggestions[] = 'group__' . $sanitized_view_mode;
-  $suggestions[] = 'group__' . $group->bundle();
-  $suggestions[] = 'group__' . $group->bundle() . '__' . $sanitized_view_mode;
-  $suggestions[] = 'group__' . $group->id();
-  $suggestions[] = 'group__' . $group->id() . '__' . $sanitized_view_mode;
-
-  return $suggestions;
-}
-
-/**
- * Implements hook_theme_suggestions_HOOK().
- */
-function group_theme_suggestions_group_content(array $variables) {
-  $suggestions = [];
-
-  /** @var \Drupal\group\Entity\GroupContentInterface $group_content */
-  $group_content = $variables['elements']['#group_content'];
-  $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
-
-  $suggestions[] = 'group_content__' . $sanitized_view_mode;
-  $suggestions[] = 'group_content__' . $group_content->bundle();
-  $suggestions[] = 'group_content__' . $group_content->bundle() . '__' . $sanitized_view_mode;
-  $suggestions[] = 'group_content__' . $group_content->id();
-  $suggestions[] = 'group_content__' . $group_content->id() . '__' . $sanitized_view_mode;
-
-  return $suggestions;
-}
-
-/**
- * Prepares variables for the group template.
- *
- * Default template: group.html.twig
- *
- * @param array $variables
- *   - elements: An array of elements to display in view mode.
- *   - group: The group object.
- *   - view_mode: View mode; e.g., 'full', 'teaser', etc.
- */
-function template_preprocess_group(&$variables) {
-  /** @var \Drupal\group\Entity\GroupInterface $group */
-  $group = $variables['elements']['#group'];
-
-  $variables['group'] = $group;
-  $variables['view_mode'] = $variables['elements']['#view_mode'];
-  $variables['label'] = $group->label();
-  $variables['url'] = $group->toUrl('canonical', ['language' => $group->language()]);
-
-  // See if we are rendering the group at its canonical route.
-  $route_match = \Drupal::routeMatch();
-  if ($route_match->getRouteName() == 'entity.group.canonical') {
-    $page_group = $route_match->getParameter('group');
-  }
-  $is_page = (!empty($page_group) ? $page_group->id() == $group->id() : FALSE);
-  $variables['page'] = $variables['view_mode'] == 'full' && $is_page;
-
-  // Helpful $content variable for templates.
-  $variables += array('content' => array());
-  foreach (Element::children($variables['elements']) as $key) {
-    $variables['content'][$key] = $variables['elements'][$key];
-  }
-}
-
-/**
- * Prepares variables for the group content template.
- *
- * Default template: group-content.html.twig
- *
- * @param array $variables
- *   - elements: An array of elements to display in view mode.
- *   - group_content: The group content object.
- *   - view_mode: View mode; e.g., 'full', 'teaser', etc.
- */
-function template_preprocess_group_content(&$variables) {
-  /** @var \Drupal\group\Entity\GroupContentInterface $group_content */
-  $group_content = $variables['elements']['#group_content'];
-
-  $variables['group_content'] = $group_content;
-  $variables['view_mode'] = $variables['elements']['#view_mode'];
-  $variables['label'] = $group_content->label();
-  $variables['url'] = $group_content->toUrl('canonical', ['language' => $group_content->language()]);
-
-  // See if we are rendering the group at its canonical route.
-  $route_match = \Drupal::routeMatch();
-  if ($route_match->getRouteName() == 'entity.group_content.canonical') {
-    $page_group_content = $route_match->getParameter('group_content');
-  }
-  $is_page = (!empty($page_group_content) ? $page_group_content->id() == $group_content->id() : FALSE);
-  $variables['page'] = $variables['view_mode'] == 'full' && $is_page;
-
-  // Helpful $content variable for templates.
-  $variables += array('content' => array());
-  foreach (Element::children($variables['elements']) as $key) {
-    $variables['content'][$key] = $variables['elements'][$key];
-  }
-}
-
-/**
- * Gets the group content enabler plugin manager.
- *
- * @return \Drupal\group\Plugin\GroupContentEnablerManagerInterface
- *   The group content enabler plugin manager.
- *
- * @internal Try to properly inject the service when possible.
- */
-function _group_content_enabler_manager() {
-  return \Drupal::service('plugin.manager.group_content_enabler');
-}
-
-/**
- * Implements hook_rebuild().
- */
-function group_rebuild() {
-  _group_content_enabler_manager()->installEnforced();
-}
-
-/**
- * Implements hook_modules_installed().
- */
-function group_modules_installed($modules) {
-  _group_content_enabler_manager()->installEnforced();
-}
-
-/**
- * Implements hook_form_FORM_ID_alter().
- *
- * @param array $form
- * @param \Drupal\Core\Form\FormStateInterface $form_state
- * @param string $form_id
- */
-function group_form_block_form_alter(&$form, FormStateInterface $form_state, $form_id) {
-  if (isset($form['visibility']['group_type'])) {
-    $form['visibility_tabs']['#attached']['library'][] = 'group/block';
-    $form['visibility']['group_type']['#title'] = t('Group types');
-    $form['visibility']['group_type']['negate']['#type'] = 'value';
-    $form['visibility']['group_type']['negate']['#title_display'] = 'invisible';
-    $form['visibility']['group_type']['negate']['#value'] = $form['visibility']['group_type']['negate']['#default_value'];
-  }
-}
-
-/**
- * Implements hook_entity_delete().
- */
-function group_entity_delete(EntityInterface $entity) {
-  if ($entity instanceof ContentEntityInterface) {
-    if ($group_contents = GroupContent::loadByEntity($entity)) {
-      /** @var \Drupal\group\Entity\GroupContent $group_content */
-      foreach ($group_contents as $group_content) {
-        $group_content->delete();
-      }
-    }
-  }
-}
-
-/**
- * Implements hook_entity_field_access().
- *
- * {@inheritdoc}
- *
- * @todo Move this to a form controller so we can hide the field if it has no
- *       options available to it?
- */
-function group_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
-  // We only care about editing the group_roles field for now.
-  if ($field_definition->getName() != 'group_roles' || $operation !== 'edit') {
-    return AccessResult::neutral();
-  }
-
-  // Can't retrieve an entity from an empty item list.
-  if (!isset($items)) {
-    return AccessResult::neutral();
-  }
-
-  /** @var \Drupal\group\Entity\GroupContent $group_content */
-  $group_content = $items->getEntity();
-  $group = $group_content->getGroup();
-
-  // Just to be safe, let's check the plugin ID.
-  if ($group_content->getContentPlugin()->getPluginId() == 'group_membership') {
-    // Only group administrators should be able to change the membership roles.
-    return AccessResult::forbiddenIf(!$group->hasPermission('administer members', $account));
-  }
-
-  // Don't show the field if the plugin ID didn't match.
-  return AccessResult::forbidden();
-}
-
-/**
- * Implements hook_user_cancel_methods_alter().
- */
-function group_user_cancel_methods_alter(&$methods) {
-  $methods['user_cancel_block']['title'] = t('Disable the account and keep its content and groups.');
-  $methods['user_cancel_block']['description'] .= ' ' . t('Groups that were created by you will still list you as the owner.');
-  $methods['user_cancel_block_unpublish']['title'] .= ' ' . t('Does not affect groups.');
-  $methods['user_cancel_block_unpublish']['description'] .= ' ' . t('Groups that were created by you will remain visible.');
-  $methods['user_cancel_reassign']['title'] .= ' ' . t('Reassign its groups to the super administrator.');
-  $methods['user_cancel_reassign']['description'] .= ' ' . t('All of your groups will be assigned to the super administrator.');
-  $methods['user_cancel_delete']['title'] = t('Delete the account, its content and groups.');
-  $methods['user_cancel_delete']['description'] .= ' ' . t('This includes groups that were created by you, including all of their content relationships!');
-}
-
-/**
- * Implements hook_user_cancel().
- */
-function group_user_cancel($edit, $account, $method) {
-  // Reassign all groups to the super user.
-  if ($method == 'user_cancel_reassign') {
-    $storage = \Drupal::entityTypeManager()->getStorage('group');
-    $gids = $storage->getQuery()
-      ->condition('uid', $account->id())
-      ->execute();
-
-    // Run this as a batch if there are more than 10 groups.
-    if (count($gids) > 10) {
-      batch_set(['operations' => [['_group_mass_reassign_to_super_user', [$gids]]]]);
-    }
-    // Run it immediately if not.
-    else {
-      foreach ($storage->loadMultiple($gids) as $group) {
-        /** @var \Drupal\group\Entity\GroupInterface $group */
-        $group->set('uid', 1);
-        $storage->save($group);
-      }
-    }
-  }
-}
-
-/**
- * Implements callback_batch_operation().
- *
- * Mass reassigns ownership of groups to the super user.
- *
- * @param int[] $ids
- *   An array of group IDs.
- */
-function _group_mass_reassign_to_super_user(array $ids, &$context) {
-  if (!isset($context['sandbox']['progress'])) {
-    $context['sandbox']['progress'] = 0;
-    $context['sandbox']['max'] = count($ids);
-    $context['sandbox']['ids'] = $ids;
-  }
-
-  // Try to update 10 groups at a time.
-  $ids = array_slice($context['sandbox']['ids'], $context['sandbox']['progress'], 10);
-
-  $storage = \Drupal::entityTypeManager()->getStorage('group');
-  foreach ($storage->loadMultiple($ids) as $group) {
-    /** @var \Drupal\group\Entity\GroupInterface $group */
-    $group->set('uid', 1);
-    $storage->save($group);
-    $context['sandbox']['progress']++;
-  }
-
-  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
-    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
-  }
-}
-
-/**
- * Implements hook_ENTITY_TYPE_delete().
- */
-function group_user_delete(EntityInterface $account) {
-  // If a user is deleted, we delete all of their groups too.
-  $storage = \Drupal::entityTypeManager()->getStorage('group');
-  if ($groups = $storage->loadByProperties(['uid' => $account->id()])) {
-    $storage->delete($groups);
-  }
-}
-
-/**
- * Implements hook_form_alter().
- */
-function group_form_alter(&$form, FormStateInterface $form_state, $form_id) {
-  // GroupContentController::createForm() tends to load entity forms for adding
-  // entities to a group. We need to add or alter the submit handlers of those
-  // forms for the process to work properly.
-  if ($form_state->getFormObject() instanceof ContentEntityForm && $form_state->has('group_content_enabler')) {
-    if ($wizard = $form_state->has('store_id')) {
-      $store = \Drupal::service('user.private_tempstore')->get('group_content_wizard');
-      $store_id = $form_state->get('store_id');
-
-      // Bail out if we are on step 2 of the wizard. We only want to alter the
-      // submit handlers for the first step or if we are not in a wizard.
-      if ($store->get("$store_id:step") === 2) {
-        return;
-      }
-    }
-
-    foreach (Element::children($form['actions']) as $name) {
-      // Remove preview button as it redirects back to the wrong form.
-      if ($name == 'preview') {
-        unset($form['actions'][$name]);
-        continue;
-      }
-
-      // Skip buttons without submit handlers.
-      if (empty($form['actions'][$name]['#submit'])) {
-        continue;
-      }
-
-      // Skip buttons that do not properly build and save an entity.
-      $submit = $form['actions'][$name]['#submit'];
-      if (!in_array('::submitForm', $submit) || !in_array('::save', $submit)) {
-        continue;
-      }
-
-      // If we are using the wizard, we need to substitute the entity save
-      // handler in order to add the entity to the private temp store.
-      if ($wizard) {
-        foreach ($submit as $key => $handler) {
-          if ($handler == '::save') {
-            $form['actions'][$name]['#submit'][$key] = 'group_content_wizard_store';
-          }
-        }
-      }
-      // Otherwise, we can simply add our submit handler and be done with it.
-      else {
-        $form['actions'][$name]['#submit'][] = 'group_content_entity_submit';
-      }
-    }
-
-    // If we are using the wizard, we also add a cancel button to step 1.
-    if ($wizard) {
-      $form['actions']['cancel'] = [
-        '#type' => 'submit',
-        '#value' => t('Cancel'),
-        '#submit' => ['group_content_wizard_cancel'],
-        '#limit_validation_errors' => [],
-      ];
-    }
-  }
-}
-
-/**
- * Stores a content entity from the wizard step 1 in the temp store.
- *
- * @see group_form_alter()
- * @see \Drupal\group\Entity\Controller\GroupContentController::createForm()
- */
-function group_content_wizard_store($form, FormStateInterface $form_state) {
-  /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
-  $entity = $form_state->getFormObject()->getEntity();
-
-  // Store the unsaved entity in the temp store.
-  $store = \Drupal::service('user.private_tempstore')->get('group_content_wizard');
-  $store_id = $form_state->get('store_id');
-  $store->set("$store_id:entity", $entity);
-  $store->set("$store_id:step", 2);
-
-  // Disable any URL-based redirect until the final step.
-  $request = \Drupal::service('request_stack')->getCurrentRequest();
-  $form_state->setRedirect('<current>', [], ['query' => $request->query->all()]);
-  $request->query->remove('destination');
-}
-
-/**
- * Cancels the wizard for group content creation.
- *
- * @see group_form_alter()
- * @see \Drupal\group\Entity\Controller\GroupContentController::createForm()
- */
-function group_content_wizard_cancel($form, FormStateInterface $form_state) {
-  $store = \Drupal::service('user.private_tempstore')->get('group_content_wizard');
-  $store_id = $form_state->get('store_id');
-  $store->delete("$store_id:entity");
-  $store->delete("$store_id:step");
-
-  /** @var \Drupal\group\Entity\GroupInterface $group */
-  $group = $form_state->get('group');
-
-  // Redirect to the group page if no destination was set in the URL.
-  $form_state->setRedirect('entity.group.canonical', ['group' => $group->id()]);
-}
-
-/**
- * Adds a newly saved entity to a group.
- *
- * @see group_form_alter()
- * @see \Drupal\group\Entity\Controller\GroupContentController::createForm()
- */
-function group_content_entity_submit($form, FormStateInterface $form_state) {
-  /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
-  $entity = $form_state->getFormObject()->getEntity();
-
-  /** @var \Drupal\group\Entity\GroupInterface $group */
-  $group = $form_state->get('group');
-  $group->addContent($entity, $form_state->get('group_content_enabler'));
-
-  // This submit handler is only called when creating new content within a group
-  // without using the 2-step wizard. We can therefore safely assume the user
-  // wants to see the entity itself and not the relationship (group content).
-  // This only applies if there was no destination GET parameter set in the URL.
-  if ($entity->access('view')) {
-    $form_state->setRedirectUrl($entity->toUrl());
-  }
-  elseif ($group->access('view')) {
-    $form_state->setRedirectUrl($group->toUrl());
-  }
-  else {
-    $form_state->setRedirect('<front>');
-  }
-}
-
-/**
- * @defgroup group_access Group access rights
- * @{
- * The group access system determines who can do what in which groups.
- *
- * Each group type can specify an unlimited amount of group roles. Just like
- * user roles in the global scope, a group role can be assigned specific
- * permissions. Users who are then given such group roles will be able to
- * perform any action their permissions allow them.
- *
- * There are three categories of users who are eligible to receive group roles:
- * - Anonymous: These users do not have a site account and will only receive the
- *   'anonymous' group role, which typically grants them a very limited set of
- *   permissions.
- * - Outsider: These users have a site account, but are not yet a member of the
- *   group in question. They will only receive the 'outsider' group role. This
- *   role is usually more permissive than 'anonymous'.
- * - Member: These users have a site account and are part of the group. They
- *   will automatically receive the 'member' role but can be assigned any other
- *   user defined group role. Common examples are: Editor, Admin, etc.
- *
- * Please keep in mind that the 'anonymous', 'outsider' and 'member' role will
- * always be assigned because they're assumed roles based on the user's account
- * status.
- */
-
-// Nothing to see here yet, our own access hook implementations will go here.
-
-/**
- * @} End of "defgroup group_access".
- */
diff --git a/web/modules/group/group.permissions.yml b/web/modules/group/group.permissions.yml
deleted file mode 100644
index 027d67e60a..0000000000
--- a/web/modules/group/group.permissions.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-bypass group access:
-  title: 'Bypass group access control'
-  description: 'Gain full control over all groups and group configuration.'
-  restrict access: TRUE
-administer group:
-  title: 'Administer group settings'
-  description: 'Gain full control over all group configuration.'
-  restrict access: TRUE
-
-permission_callbacks:
-  - '\Drupal\group\Access\GroupPermissions::groupTypePermissions'
diff --git a/web/modules/group/group.post_update.php b/web/modules/group/group.post_update.php
deleted file mode 100644
index 8512c90034..0000000000
--- a/web/modules/group/group.post_update.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-/**
- * @file
- * Post update functions for Group.
- */
-
-use Drupal\group\Entity\GroupType;
-use Drupal\group\Entity\GroupContentType;
-
-/**
- * Recalculate group type and group content type dependencies after moving the
- * plugin configuration from the former to the latter in group_update_8006().
- */
-function group_post_update_group_type_group_content_type_dependencies() {
-  foreach (GroupType::loadMultiple() as $group_type) {
-    $group_type->save();
-  }
-
-  foreach (GroupContentType::loadMultiple() as $group_type) {
-    $group_type->save();
-  }
-}
-
-/**
- * Recalculate group content type dependencies after updating the group content
- * enabler base plugin dependency logic.
- */
-function group_post_update_group_content_type_dependencies() {
-  foreach (GroupContentType::loadMultiple() as $group_type) {
-    $group_type->save();
-  }
-}
diff --git a/web/modules/group/group.routing.yml b/web/modules/group/group.routing.yml
deleted file mode 100644
index 7e855de7da..0000000000
--- a/web/modules/group/group.routing.yml
+++ /dev/null
@@ -1,89 +0,0 @@
-# General routes for the Group module.
-group.settings:
-  path: 'admin/group/settings'
-  defaults:
-    _form: '\Drupal\group\Form\GroupSettingsForm'
-    _title: 'Group settings'
-  requirements:
-    _permission: 'administer group'
-
-# Group entity routes.
-# Common entity routes are generated by \Drupal\group\Entity\Routing\GroupRouteProvider.
-entity.group.join:
-  path: '/group/{group}/join'
-  defaults:
-    _controller: '\Drupal\group\Controller\GroupMembershipController::join'
-    _title_callback: '\Drupal\group\Controller\GroupMembershipController::joinTitle'
-  requirements:
-    _group_permission: 'join group'
-    _group_member: 'FALSE'
-
-entity.group.leave:
-  path: '/group/{group}/leave'
-  defaults:
-    _controller: '\Drupal\group\Controller\GroupMembershipController::leave'
-  requirements:
-    _group_permission: 'leave group'
-    _group_member: 'TRUE'
-
-# Group type entity routes.
-# Common entity routes are generated by \Drupal\group\Entity\Routing\GroupTypeRouteProvider.
-entity.group_type.permissions_form:
-  path: '/admin/group/types/manage/{group_type}/permissions'
-  defaults:
-    _form: '\Drupal\group\Form\GroupPermissionsTypeSpecificForm'
-    _title: 'Edit group type permissions'
-  requirements:
-    _permission: 'administer group'
-
-entity.group_type.content_plugins:
-  path: '/admin/group/types/manage/{group_type}/content'
-  defaults:
-    _controller: '\Drupal\group\Entity\Controller\GroupTypeController::content'
-    _title: 'Configure available content'
-  requirements:
-    _permission: 'administer group'
-
-# Group role entity routes.
-# Common entity routes are generated by \Drupal\group\Entity\Routing\GroupRoleRouteProvider.
-entity.group_role.permissions_form:
-  path: '/admin/group/types/manage/{group_type}/roles/{group_role}/permissions'
-  defaults:
-    _form: '\Drupal\group\Form\GroupPermissionsRoleSpecificForm'
-    _title: 'Edit group role permissions'
-  requirements:
-    _permission: 'administer group'
-  options:
-      parameters:
-        group_type:
-          type: 'entity:group_type'
-
-# Group content type entity routes.
-# todo Move to group type path when https://www.drupal.org/node/2651974 lands.
-# todo When moved, remove the breadcrumb generator.
-
-# todo This route needs a requirement which only allows access if the plugin
-#      isn't installed on the group type yet.
-entity.group_content_type.add_form:
-  path: '/admin/group/content/install/{group_type}/{plugin_id}'
-  defaults:
-    _entity_form: 'group_content_type.add'
-    _title: 'Install content plugin'
-  requirements:
-    _permission: 'administer group'
-
-entity.group_content_type.edit_form:
-  path: '/admin/group/content/manage/{group_content_type}'
-  defaults:
-    _entity_form: 'group_content_type.edit'
-    _title: 'Configure content plugin'
-  requirements:
-    _permission: 'administer group'
-
-entity.group_content_type.delete_form:
-  path: '/admin/group/content/manage/{group_content_type}/uninstall'
-  defaults:
-    _entity_form: 'group_content_type.delete'
-    _title: 'Uninstall content plugin'
-  requirements:
-    _permission: 'administer group'
diff --git a/web/modules/group/group.services.yml b/web/modules/group/group.services.yml
deleted file mode 100644
index 44776bdcc4..0000000000
--- a/web/modules/group/group.services.yml
+++ /dev/null
@@ -1,102 +0,0 @@
-services:
-  access_check.group.permission:
-    class: 'Drupal\group\Access\GroupPermissionAccessCheck'
-    tags:
-      - { name: 'access_check', applies_to: '_group_permission' }
-  access_check.group.member:
-    class: 'Drupal\group\Access\GroupMemberAccessCheck'
-    tags:
-      - { name: 'access_check', applies_to: '_group_member' }
-  access_check.group.installed_content:
-    class: 'Drupal\group\Access\GroupInstalledContentAccessCheck'
-    tags:
-      - { name: 'access_check', applies_to: '_group_installed_content' }
-  access_check.group.owns_content:
-    class: 'Drupal\group\Access\GroupOwnsContentAccessCheck'
-    tags:
-      - { name: 'access_check', applies_to: '_group_owns_content' }
-  access_check.group_content.create:
-    class: 'Drupal\group\Access\GroupContentCreateAccessCheck'
-    arguments: ['@entity.manager']
-    tags:
-      - { name: 'access_check', applies_to: '_group_content_create_access' }
-  access_check.group_content.create_any:
-    class: 'Drupal\group\Access\GroupContentCreateAnyAccessCheck'
-    arguments: ['@entity.manager']
-    tags:
-      - { name: 'access_check', applies_to: '_group_content_create_any_access' }
-  access_check.group_content.create_entity:
-    class: 'Drupal\group\Access\GroupContentCreateEntityAccessCheck'
-    tags:
-      - { name: 'access_check', applies_to: '_group_content_create_entity_access' }
-  access_check.group_content.create_any_entity:
-    class: 'Drupal\group\Access\GroupContentCreateAnyEntityAccessCheck'
-    tags:
-      - { name: 'access_check', applies_to: '_group_content_create_any_entity_access' }
-
-  cache_context.group:
-    class: 'Drupal\group\Cache\Context\GroupCacheContext'
-    arguments: ['@current_route_match']
-    tags:
-      - { name: 'cache.context'}
-  cache_context.group.type:
-    class: 'Drupal\group\Cache\Context\GroupTypeCacheContext'
-    arguments: ['@current_route_match']
-    tags:
-      - { name: 'cache.context'}
-  cache_context.group_membership:
-    class: 'Drupal\group\Cache\Context\GroupMembershipCacheContext'
-    arguments: ['@current_route_match', '@current_user', '@entity_type.manager']
-    tags:
-      - { name: 'cache.context'}
-  cache_context.group_membership.audience:
-    class: 'Drupal\group\Cache\Context\GroupMembershipAudienceCacheContext'
-    arguments: ['@current_route_match', '@current_user', '@entity_type.manager']
-    tags:
-      - { name: 'cache.context'}
-  cache_context.group_membership.roles:
-    class: 'Drupal\group\Cache\Context\GroupMembershipRolesCacheContext'
-    arguments: ['@current_route_match', '@current_user', '@entity_type.manager']
-    tags:
-      - { name: 'cache.context'}
-  cache_context.group_membership.roles.permissions:
-    class: 'Drupal\group\Cache\Context\GroupMembershipPermissionsCacheContext'
-    arguments: ['@current_route_match', '@current_user', '@entity_type.manager', '@group.permissions_hash_generator']
-    tags:
-      - { name: 'cache.context'}
-
-  group.admin_path.route_subscriber:
-    class: 'Drupal\group\Routing\GroupAdminRouteSubscriber'
-    arguments: ['@config.factory']
-    tags:
-      - { name: 'event_subscriber' }
-
-  group.group_route_context:
-    class: 'Drupal\group\Context\GroupRouteContext'
-    arguments: ['@current_route_match']
-    tags:
-      - { name: 'context_provider' }
-  group.membership_loader:
-    class: 'Drupal\group\GroupMembershipLoader'
-    arguments: ['@entity_type.manager', '@current_user']
-  group.permissions:
-    class: 'Drupal\group\Access\GroupPermissionHandler'
-    arguments: ['@module_handler', '@string_translation', '@controller_resolver', '@plugin.manager.group_content_enabler']
-  group.permissions_hash_generator:
-    class: 'Drupal\group\Access\GroupPermissionsHashGenerator'
-    arguments: ['@private_key', '@cache.default', '@cache.static', '@entity_type.manager']
-  group.uninstall_validator.group_content:
-    class: 'Drupal\group\UninstallValidator\GroupContentUninstallValidator'
-    tags:
-      - { name: 'module_install.uninstall_validator' }
-    arguments: ['@string_translation', '@entity.query', '@plugin.manager.group_content_enabler']
-    lazy: 'true'
-
-  group_content_type.breadcrumb:
-    class: 'Drupal\group\Breadcrumb\GroupContentTypeBreadcrumbBuilder'
-    tags:
-      - { name: 'breadcrumb_builder', priority: 100 }
-
-  plugin.manager.group_content_enabler:
-    class: 'Drupal\group\Plugin\GroupContentEnablerManager'
-    arguments: ['@container.namespaces', '@cache.discovery', '@module_handler', '@entity_type.manager']
diff --git a/web/modules/group/group.tokens.inc b/web/modules/group/group.tokens.inc
deleted file mode 100644
index 4e7f76aa17..0000000000
--- a/web/modules/group/group.tokens.inc
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-
-/**
- * @file
- * Builds placeholder replacement tokens for group-related data.
- */
-
-use Drupal\Core\Datetime\Entity\DateFormat;
-use Drupal\Core\Language\LanguageInterface;
-use Drupal\Core\Render\BubbleableMetadata;
-use Drupal\user\Entity\User;
-
-/**
- * Implements hook_token_info().
- */
-function group_token_info() {
-  $type = [
-    'name' => t('Group'),
-    'description' => t('Tokens related to individual groups.'),
-    'needs-data' => 'group',
-  ];
-
-  $group['id'] = [
-    'name' => t('Group ID'),
-    'description' => t('The unique ID of the group.'),
-  ];
-
-  $group['type'] = [
-    'name' => t('Group type'),
-    'description' => t('The machine name of the group type.'),
-  ];
-
-  $group['type-name'] = [
-    'name' => t('Group type name'),
-    'description' => t('The human-readable name of the group type.'),
-  ];
-
-  $group['title'] = [
-    'name' => t('Title'),
-  ];
-
-  $group['url'] = [
-    'name' => t('URL'),
-    'description' => t('The URL of the group.'),
-  ];
-
-  $group['edit-url'] = [
-    'name' => t('Edit URL'),
-    'description' => t('The URL of the group\'s edit page.'),
-  ];
-
-  $group['created'] = [
-    'name' => t('Date created'),
-    'type' => 'date',
-  ];
-
-  $group['changed'] = [
-    'name' => t('Date changed'),
-    'description' => t('The date the group was most recently updated.'),
-    'type' => 'date',
-  ];
-
-  $group['author'] = [
-    'name' => t('Author'),
-    'type' => 'user',
-  ];
-
-  return [
-    'types' => ['group' => $type],
-    'tokens' => ['group' => $group],
-  ];
-}
-
-/**
- * Implements hook_tokens().
- */
-function group_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
-  $token_service = \Drupal::token();
-
-  $url_options = ['absolute' => TRUE];
-  if (isset($options['langcode'])) {
-    $url_options['language'] = \Drupal::languageManager()->getLanguage($options['langcode']);
-    $langcode = $options['langcode'];
-  }
-  else {
-    $langcode = LanguageInterface::LANGCODE_DEFAULT;
-  }
-  $replacements = [];
-
-  if ($type == 'group' && !empty($data['group'])) {
-    /** @var \Drupal\group\Entity\GroupInterface $group */
-    $group = $data['group'];
-
-    foreach ($tokens as $name => $original) {
-      switch ($name) {
-        case 'id':
-          $replacements[$original] = $group->id();
-          break;
-
-        case 'type':
-          $replacements[$original] = $group->bundle();
-          break;
-
-        case 'type-name':
-          $replacements[$original] = $group->getGroupType()->label();
-          break;
-
-        case 'title':
-          $replacements[$original] = $group->label();
-          break;
-
-        case 'langcode':
-          $replacements[$original] = $group->language()->getId();
-          break;
-
-        case 'url':
-          $replacements[$original] = $group->toUrl('canonical', $url_options)->toString();
-          break;
-
-        case 'edit-url':
-          $replacements[$original] = $group->toUrl('edit-form', $url_options)->toString();
-          break;
-
-        // Default values for the chained tokens handled below.
-        case 'author':
-          $account = $group->getOwner();
-          $bubbleable_metadata->addCacheableDependency($account);
-          $replacements[$original] = $account->label();
-          break;
-
-        case 'created':
-          $date_format = DateFormat::load('medium');
-          $bubbleable_metadata->addCacheableDependency($date_format);
-          $replacements[$original] = \Drupal::service('date.formatter')->format($group->getCreatedTime(), 'medium', '', NULL, $langcode);
-          break;
-
-        case 'changed':
-          $date_format = DateFormat::load('medium');
-          $bubbleable_metadata->addCacheableDependency($date_format);
-          $replacements[$original] = \Drupal::service('date.formatter')->format($group->getChangedTime(), 'medium', '', NULL, $langcode);
-          break;
-      }
-    }
-
-    if ($author_tokens = $token_service->findWithPrefix($tokens, 'author')) {
-      $replacements += $token_service->generate('user', $author_tokens, ['user' => $group->getOwner()], $options, $bubbleable_metadata);
-    }
-
-    if ($created_tokens = $token_service->findWithPrefix($tokens, 'created')) {
-      $replacements += $token_service->generate('date', $created_tokens, ['date' => $group->getCreatedTime()], $options, $bubbleable_metadata);
-    }
-
-    if ($changed_tokens = $token_service->findWithPrefix($tokens, 'changed')) {
-      $replacements += $token_service->generate('date', $changed_tokens, ['date' => $group->getChangedTime()], $options, $bubbleable_metadata);
-    }
-  }
-
-  return $replacements;
-}
diff --git a/web/modules/group/group.views.inc b/web/modules/group/group.views.inc
deleted file mode 100644
index da4753ea8b..0000000000
--- a/web/modules/group/group.views.inc
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains Views hooks.
- */
-
-/**
- * Implements hook_views_data_alter().
- */
-function group_views_data_alter(array &$data) {
-  $entity_type_manager = \Drupal::entityTypeManager();
-  $entity_types = $entity_type_manager->getDefinitions();
-
-  // Get the data table for GroupContent entities.
-  $data_table = $entity_types['group_content']->getDataTable();
-
-  /** @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager */
-  $plugin_manager = \Drupal::service('plugin.manager.group_content_enabler');
-
-  // Add views data for all defined plugins so modules can provide default
-  // views even though their plugins may not have been installed yet.
-  foreach ($plugin_manager->getAll() as $plugin) {
-    $entity_type_id = $plugin->getEntityTypeId();
-    $entity_type = $entity_types[$entity_type_id];
-    $entity_data_table = $entity_type->getDataTable() ?: $entity_type->getBaseTable();
-
-    // We only add one 'group_content' entry per entity type.
-    if (isset($data[$entity_data_table]['group_content'])) {
-      continue;
-    }
-
-    $t_args = [
-      '@entity_type' => $entity_type->getLabel(),
-    ];
-
-    // This relationship will allow a content entity to easily map to the group
-    // content entity that ties it to a group, optionally filtering by plugin.
-    $data[$entity_data_table]['group_content'] = array(
-      'title' => t('Group content for @entity_type', $t_args),
-      'help' => t('Relates to the group content entities that represent the @entity_type.', $t_args),
-      'relationship' => array(
-        'group' => t('Group content'),
-        'base' => $data_table,
-        'base field' => 'entity_id',
-        'relationship field' => $entity_type->getKey('id'),
-        'id' => 'group_content_to_entity_reverse',
-        'label' => t('@entity_type group content', $t_args),
-      ),
-    );
-  }
-}
diff --git a/web/modules/group/images/icons/000000/toolbar.svg b/web/modules/group/images/icons/000000/toolbar.svg
deleted file mode 100644
index f908d0f865..0000000000
--- a/web/modules/group/images/icons/000000/toolbar.svg
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
-<path d="M11.638,7.496c1.961,0,3.552,1.59,3.552,3.55V16H8.086v-4.953C8.086,9.086,9.675,7.496,11.638,7.496z"/>
-<g>
-	<path d="M7.624,10.865c0-1.889,1.388-3.448,3.194-3.743V5.349c0-2.517-2.116-4.557-4.727-4.557c-2.611,0-4.728,2.041-4.728,4.557
-		V16h6.261V10.865z"/>
-</g>
-<path fill="#FFFFFF" d="M4.076,6.412c0,0,0.168,0.269,0.549,0.573C4.99,7.295,5.597,7.578,6.246,7.581
-	c0.322-0.01,0.642-0.067,0.932-0.167c0.29-0.101,0.546-0.229,0.757-0.358C8.155,6.944,8.307,6.8,8.429,6.723
-	C8.546,6.638,8.614,6.59,8.614,6.59l0.062,0.076c0,0-0.066,0.051-0.183,0.141C8.373,6.889,8.222,7.04,8,7.162
-	C7.787,7.3,7.527,7.441,7.228,7.555C6.93,7.668,6.593,7.74,6.249,7.761C6.077,7.746,5.902,7.765,5.736,7.722
-	C5.567,7.697,5.405,7.652,5.253,7.595C4.95,7.482,4.684,7.33,4.479,7.171C4.065,6.862,3.862,6.562,3.862,6.562L4.076,6.412z"/>
-<ellipse fill="#FFFFFF" cx="4.966" cy="4.368" rx="0.94" ry="1.134"/>
-<ellipse fill="#FFFFFF" cx="7.693" cy="4.221" rx="0.959" ry="1.134"/>
-<ellipse cx="5.023" cy="4.221" rx="0.487" ry="0.55"/>
-<ellipse cx="7.694" cy="4.074" rx="0.487" ry="0.551"/>
-<path fill="#FFFFFF" d="M3.928,3.063c0,0,0.028-0.081,0.097-0.189c0.069-0.108,0.187-0.235,0.324-0.347
-	c0.15-0.101,0.333-0.142,0.468-0.142c0.136,0.021,0.218,0.047,0.218,0.047C5.06,2.44,5.073,2.467,5.065,2.491
-	C5.06,2.509,5.044,2.521,5.027,2.523L5.011,2.525c0,0-0.081,0.011-0.188,0.007C4.712,2.542,4.579,2.6,4.454,2.68
-	C4.202,2.848,4.011,3.111,4.011,3.111c-0.016,0.021-0.046,0.026-0.067,0.01C3.926,3.109,3.92,3.083,3.928,3.063z"/>
-<path fill="#FFFFFF" d="M8.667,3.111c0,0-0.195-0.258-0.442-0.433C8.103,2.591,7.964,2.54,7.854,2.53
-	c-0.109,0-0.188-0.005-0.188-0.005L7.649,2.524C7.624,2.522,7.604,2.5,7.606,2.474c0.001-0.021,0.016-0.037,0.035-0.042
-	c0,0,0.083-0.021,0.218-0.044c0.134,0,0.313,0.048,0.467,0.142c0.144,0.104,0.256,0.239,0.326,0.344
-	C8.726,2.98,8.75,3.063,8.75,3.063l0.001,0.006c0.007,0.024-0.007,0.052-0.033,0.059C8.699,3.133,8.678,3.126,8.667,3.111z"/>
-<ellipse fill="#FFFFFF" cx="12.244" cy="10.258" rx="0.842" ry="0.944"/>
-<ellipse fill="#FFFFFF" cx="10.024" cy="10.135" rx="0.801" ry="0.944"/>
-<ellipse cx="12.252" cy="10.135" rx="0.407" ry="0.46"/>
-<ellipse cx="10.023" cy="10.011" rx="0.407" ry="0.459"/>
-<path fill="#FFFFFF" d="M13.17,9.054c0,0-0.22-0.164-0.47-0.214c-0.121-0.037-0.244-0.04-0.336-0.019
-	c-0.088,0.035-0.147,0.058-0.147,0.058l-0.012,0.005c-0.02,0.008-0.043-0.002-0.05-0.021c-0.008-0.019,0-0.04,0.018-0.049
-	c0,0,0.063-0.036,0.159-0.09c0.104-0.041,0.257-0.057,0.404-0.03c0.284,0.094,0.485,0.299,0.485,0.299
-	c0.017,0.015,0.017,0.041,0.001,0.057C13.21,9.063,13.186,9.064,13.17,9.054z"/>
-<path fill="#FFFFFF" d="M9.494,8.832c0,0,0.239-0.165,0.533-0.186c0.147-0.001,0.294,0.04,0.388,0.096
-	c0.086,0.068,0.144,0.113,0.144,0.113c0.018,0.014,0.02,0.039,0.007,0.056c-0.013,0.016-0.036,0.019-0.053,0.008L10.5,8.911
-	c0,0-0.053-0.035-0.131-0.089c-0.085-0.042-0.208-0.066-0.336-0.056C9.776,8.784,9.533,8.901,9.533,8.901
-	c-0.02,0.01-0.045,0.002-0.054-0.019C9.47,8.865,9.477,8.842,9.494,8.832z"/>
-<ellipse fill="#FFFFFF" cx="10.95" cy="13.282" rx="0.407" ry="0.598"/>
-<path fill="#FFFFFF" d="M4.284,6.218c0,0-0.006,0.013-0.019,0.034c-0.012,0.021-0.031,0.05-0.057,0.084
-	C4.195,6.353,4.181,6.37,4.165,6.388C4.148,6.406,4.13,6.424,4.11,6.442C4.091,6.459,4.07,6.478,4.048,6.495
-	C4.025,6.512,4,6.527,3.976,6.542C3.95,6.557,3.924,6.569,3.897,6.581C3.871,6.591,3.843,6.6,3.816,6.605
-	c-0.027,0.007-0.054,0.01-0.08,0.011c-0.025,0.002-0.05,0.001-0.072-0.002c-0.022-0.001-0.042-0.008-0.06-0.011
-	C3.588,6.598,3.573,6.593,3.561,6.589c-0.023-0.01-0.037-0.017-0.037-0.017C3.509,6.564,3.502,6.546,3.509,6.53
-	c0.006-0.012,0.02-0.02,0.033-0.017l0.003,0c0,0,0.013,0.001,0.034,0.006c0.011,0,0.024,0.002,0.039,0.003
-	c0.015,0,0.032,0.002,0.05,0c0.01,0,0.019,0,0.028-0.001c0.01-0.001,0.02-0.001,0.03-0.003c0.01-0.001,0.021-0.003,0.031-0.005
-	C3.768,6.51,3.779,6.507,3.79,6.504c0.021-0.005,0.044-0.015,0.065-0.024C3.877,6.471,3.9,6.459,3.921,6.447
-	c0.022-0.012,0.042-0.025,0.063-0.04c0.02-0.014,0.04-0.029,0.058-0.043c0.02-0.016,0.037-0.03,0.053-0.045S4.127,6.29,4.141,6.276
-	c0.028-0.027,0.05-0.051,0.066-0.067C4.222,6.192,4.23,6.183,4.23,6.183l0.001-0.001C4.244,6.169,4.263,6.168,4.276,6.18
-	C4.287,6.19,4.29,6.206,4.284,6.218z"/>
-</svg>
diff --git a/web/modules/group/images/icons/787878/toolbar.svg b/web/modules/group/images/icons/787878/toolbar.svg
deleted file mode 100644
index d4f7417ad3..0000000000
--- a/web/modules/group/images/icons/787878/toolbar.svg
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
-<path fill="#787878" d="M11.638,7.496c1.961,0,3.552,1.59,3.552,3.55V16H8.086v-4.953C8.086,9.086,9.675,7.496,11.638,7.496z"/>
-<g>
-	<path fill="#787878" d="M7.624,10.865c0-1.889,1.388-3.448,3.194-3.743V5.349c0-2.517-2.116-4.557-4.727-4.557
-		c-2.611,0-4.728,2.041-4.728,4.557V16h6.261V10.865z"/>
-</g>
-<path fill="#FFFFFF" d="M4.076,6.412c0,0,0.168,0.269,0.549,0.573C4.99,7.295,5.597,7.578,6.246,7.581
-	c0.322-0.01,0.642-0.067,0.932-0.167c0.29-0.101,0.546-0.229,0.757-0.358C8.155,6.944,8.307,6.8,8.429,6.723
-	C8.546,6.638,8.614,6.59,8.614,6.59l0.062,0.076c0,0-0.066,0.051-0.183,0.141C8.373,6.889,8.222,7.04,8,7.162
-	C7.787,7.3,7.527,7.441,7.228,7.555C6.93,7.668,6.593,7.74,6.249,7.761C6.077,7.746,5.902,7.765,5.736,7.722
-	C5.567,7.697,5.405,7.652,5.253,7.595C4.95,7.482,4.684,7.33,4.479,7.171C4.065,6.862,3.862,6.562,3.862,6.562L4.076,6.412z"/>
-<ellipse fill="#FFFFFF" cx="4.966" cy="4.368" rx="0.94" ry="1.134"/>
-<ellipse fill="#FFFFFF" cx="7.693" cy="4.221" rx="0.959" ry="1.134"/>
-<ellipse fill="#787878" cx="5.023" cy="4.221" rx="0.487" ry="0.55"/>
-<ellipse fill="#787878" cx="7.694" cy="4.074" rx="0.487" ry="0.551"/>
-<path fill="#FFFFFF" d="M3.928,3.063c0,0,0.028-0.081,0.097-0.189c0.069-0.108,0.187-0.235,0.324-0.347
-	c0.15-0.101,0.333-0.142,0.468-0.142c0.136,0.021,0.218,0.047,0.218,0.047C5.06,2.44,5.073,2.467,5.065,2.491
-	C5.06,2.509,5.044,2.521,5.027,2.523L5.011,2.525c0,0-0.081,0.011-0.188,0.007C4.712,2.542,4.579,2.6,4.454,2.68
-	C4.202,2.848,4.011,3.111,4.011,3.111c-0.016,0.021-0.046,0.026-0.067,0.01C3.926,3.109,3.92,3.083,3.928,3.063z"/>
-<path fill="#FFFFFF" d="M8.667,3.111c0,0-0.195-0.258-0.442-0.433C8.103,2.591,7.964,2.54,7.854,2.53
-	c-0.109,0-0.188-0.005-0.188-0.005L7.649,2.524C7.624,2.522,7.604,2.5,7.606,2.474c0.001-0.021,0.016-0.037,0.035-0.042
-	c0,0,0.083-0.021,0.218-0.044c0.134,0,0.313,0.048,0.467,0.142c0.144,0.104,0.256,0.239,0.326,0.344
-	C8.726,2.98,8.75,3.063,8.75,3.063l0.001,0.006c0.007,0.024-0.007,0.052-0.033,0.059C8.699,3.133,8.678,3.126,8.667,3.111z"/>
-<ellipse fill="#FFFFFF" cx="12.244" cy="10.258" rx="0.842" ry="0.944"/>
-<ellipse fill="#FFFFFF" cx="10.024" cy="10.135" rx="0.801" ry="0.944"/>
-<ellipse fill="#787878" cx="12.252" cy="10.135" rx="0.407" ry="0.46"/>
-<ellipse fill="#787878" cx="10.023" cy="10.011" rx="0.407" ry="0.459"/>
-<path fill="#FFFFFF" d="M13.17,9.054c0,0-0.22-0.164-0.47-0.214c-0.121-0.037-0.244-0.04-0.336-0.019
-	c-0.088,0.035-0.147,0.058-0.147,0.058l-0.012,0.005c-0.02,0.008-0.043-0.002-0.05-0.021c-0.008-0.019,0-0.04,0.018-0.049
-	c0,0,0.063-0.036,0.159-0.09c0.104-0.041,0.257-0.057,0.404-0.03c0.284,0.094,0.485,0.299,0.485,0.299
-	c0.017,0.015,0.017,0.041,0.001,0.057C13.21,9.063,13.186,9.064,13.17,9.054z"/>
-<path fill="#FFFFFF" d="M9.494,8.832c0,0,0.239-0.165,0.533-0.186c0.147-0.001,0.294,0.04,0.388,0.096
-	c0.086,0.068,0.144,0.113,0.144,0.113c0.018,0.014,0.02,0.039,0.007,0.056c-0.013,0.016-0.036,0.019-0.053,0.008L10.5,8.911
-	c0,0-0.053-0.035-0.131-0.089c-0.085-0.042-0.208-0.066-0.336-0.056C9.776,8.784,9.533,8.901,9.533,8.901
-	c-0.02,0.01-0.045,0.002-0.054-0.019C9.47,8.865,9.477,8.842,9.494,8.832z"/>
-<ellipse fill="#FFFFFF" cx="10.95" cy="13.282" rx="0.407" ry="0.598"/>
-<path fill="#FFFFFF" d="M4.284,6.218c0,0-0.006,0.013-0.019,0.034c-0.012,0.021-0.031,0.05-0.057,0.084
-	C4.195,6.353,4.181,6.37,4.165,6.388C4.148,6.406,4.13,6.424,4.11,6.442C4.091,6.459,4.07,6.478,4.048,6.495
-	C4.025,6.512,4,6.527,3.976,6.542C3.95,6.557,3.924,6.569,3.897,6.581C3.871,6.591,3.843,6.6,3.816,6.605
-	c-0.027,0.007-0.054,0.01-0.08,0.011c-0.025,0.002-0.05,0.001-0.072-0.002c-0.022-0.001-0.042-0.008-0.06-0.011
-	C3.588,6.598,3.573,6.593,3.561,6.589c-0.023-0.01-0.037-0.017-0.037-0.017C3.509,6.564,3.502,6.546,3.509,6.53
-	c0.006-0.012,0.02-0.02,0.033-0.017l0.003,0c0,0,0.013,0.001,0.034,0.006c0.011,0,0.024,0.002,0.039,0.003
-	c0.015,0,0.032,0.002,0.05,0c0.01,0,0.019,0,0.028-0.001c0.01-0.001,0.02-0.001,0.03-0.003c0.01-0.001,0.021-0.003,0.031-0.005
-	C3.768,6.51,3.779,6.507,3.79,6.504c0.021-0.005,0.044-0.015,0.065-0.024C3.877,6.471,3.9,6.459,3.921,6.447
-	c0.022-0.012,0.042-0.025,0.063-0.04c0.02-0.014,0.04-0.029,0.058-0.043c0.02-0.016,0.037-0.03,0.053-0.045S4.127,6.29,4.141,6.276
-	c0.028-0.027,0.05-0.051,0.066-0.067C4.222,6.192,4.23,6.183,4.23,6.183l0.001-0.001C4.244,6.169,4.263,6.168,4.276,6.18
-	C4.287,6.19,4.29,6.206,4.284,6.218z"/>
-</svg>
diff --git a/web/modules/group/js/block.js b/web/modules/group/js/block.js
deleted file mode 100644
index ef002213dd..0000000000
--- a/web/modules/group/js/block.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * @file
- * Block behaviors.
- */
-
-(function ($, window) {
-
-    'use strict';
-
-    /**
-     * Provide the summary information for the block settings vertical tabs.
-     *
-     * @type {Drupal~behavior}
-     *
-     * @prop {Drupal~behaviorAttach} attach
-     *   Attaches the behavior for the block settings summaries.
-     */
-    Drupal.behaviors.blockSettingsSummaryGroup = {
-        attach: function () {
-            // The drupalSetSummary method required for this behavior is not available
-            // on the Blocks administration page, so we need to make sure this
-            // behavior is processed only if drupalSetSummary is defined.
-            if (typeof jQuery.fn.drupalSetSummary === 'undefined') {
-                return;
-            }
-
-            /**
-             * Create a summary for checkboxes in the provided context.
-             *
-             * @param {HTMLDocument|HTMLElement} context
-             *   A context where one would find checkboxes to summarize.
-             *
-             * @return {string}
-             *   A string with the summary.
-             */
-            function checkboxesSummary(context) {
-                var vals = [];
-                var $checkboxes = $(context).find('input[type="checkbox"]:checked + label');
-                var il = $checkboxes.length;
-                for (var i = 0; i < il; i++) {
-                    vals.push($($checkboxes[i]).html());
-                }
-                if (!vals.length) {
-                    vals.push(Drupal.t('Not restricted'));
-                }
-                return vals.join(', ');
-            }
-
-            $('[data-drupal-selector="edit-visibility-group-type"]').drupalSetSummary(checkboxesSummary);
-        }
-    };
-
-})(jQuery, window);
diff --git a/web/modules/group/modules/gnode/config/optional/views.view.group_nodes.yml b/web/modules/group/modules/gnode/config/optional/views.view.group_nodes.yml
deleted file mode 100644
index c146c10ff7..0000000000
--- a/web/modules/group/modules/gnode/config/optional/views.view.group_nodes.yml
+++ /dev/null
@@ -1,947 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  module:
-    - gnode
-    - group
-    - node
-id: group_nodes
-label: 'Group nodes'
-module: gnode
-description: 'Lists all of the nodes that have been added to a group.'
-tag: ''
-base_table: node_field_data
-base_field: nid
-core: 8.x
-display:
-  default:
-    display_plugin: default
-    id: default
-    display_title: Master
-    position: 0
-    display_options:
-      access:
-        type: group_permission
-        options:
-          group_permission: 'access group_node overview'
-      cache:
-        type: tag
-        options: {  }
-      query:
-        type: views_query
-        options:
-          disable_sql_rewrite: false
-          distinct: false
-          replica: false
-          query_comment: ''
-          query_tags: {  }
-      exposed_form:
-        type: basic
-        options:
-          submit_button: Apply
-          reset_button: false
-          reset_button_label: Reset
-          exposed_sorts_label: 'Sort by'
-          expose_sort_order: true
-          sort_asc_label: Asc
-          sort_desc_label: Desc
-      pager:
-        type: full
-        options:
-          items_per_page: 50
-          offset: 0
-          id: 0
-          total_pages: null
-          tags:
-            previous: ‹‹
-            next: ››
-            first: '« First'
-            last: 'Last »'
-          expose:
-            items_per_page: false
-            items_per_page_label: 'Items per page'
-            items_per_page_options: '5, 10, 25, 50'
-            items_per_page_options_all: false
-            items_per_page_options_all_label: '- All -'
-            offset: false
-            offset_label: Offset
-          quantity: 9
-      style:
-        type: table
-        options:
-          grouping: {  }
-          row_class: ''
-          default_row_class: true
-          override: true
-          sticky: true
-          caption: ''
-          summary: ''
-          description: ''
-          columns:
-            title: title
-            type: type
-            status: status
-            changed: changed
-            view_group_content: view_group_content
-            edit_group_content: edit_group_content
-            delete_group_content: delete_group_content
-            edit_node: edit_node
-            delete_node: delete_node
-            dropbutton: dropbutton
-          info:
-            title:
-              sortable: true
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            type:
-              sortable: true
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            status:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            changed:
-              sortable: true
-              default_sort_order: desc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            view_group_content:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            edit_group_content:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            delete_group_content:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            edit_node:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            delete_node:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            dropbutton:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-          default: changed
-          empty_table: true
-      row:
-        type: fields
-        options:
-          inline: {  }
-          separator: ''
-          hide_empty: false
-          default_field_elements: true
-      fields:
-        title:
-          id: title
-          table: node_field_data
-          field: title
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: Title
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: false
-            ellipsis: false
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: string
-          settings:
-            link_to_entity: true
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: node
-          entity_field: title
-          plugin_id: field
-        type:
-          id: type
-          table: node_field_data
-          field: type
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: 'Content type'
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: target_id
-          type: entity_reference_label
-          settings:
-            link: false
-          group_column: target_id
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: node
-          entity_field: type
-          plugin_id: field
-        status:
-          id: status
-          table: node_field_data
-          field: status
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: Status
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: boolean
-          settings:
-            format: custom
-            format_custom_true: Published
-            format_custom_false: Unpublished
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: node
-          entity_field: status
-          plugin_id: field
-        changed:
-          id: changed
-          table: node_field_data
-          field: changed
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: Updated
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: timestamp
-          settings:
-            date_format: short
-            custom_date_format: ''
-            timezone: ''
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: node
-          entity_field: changed
-          plugin_id: field
-        view_group_content:
-          id: view_group_content
-          table: group_content
-          field: view_group_content
-          relationship: group_content
-          group_type: group
-          admin_label: 'View relation link'
-          label: 'Link to Group content'
-          exclude: true
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          text: 'View relation'
-          entity_type: group_content
-          plugin_id: entity_link
-        edit_group_content:
-          id: edit_group_content
-          table: group_content
-          field: edit_group_content
-          relationship: group_content
-          group_type: group
-          admin_label: 'Edit relation link'
-          label: 'Link to edit Group content'
-          exclude: true
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          text: 'Edit relation'
-          entity_type: group_content
-          plugin_id: entity_link_edit
-        delete_group_content:
-          id: delete_group_content
-          table: group_content
-          field: delete_group_content
-          relationship: group_content
-          group_type: group
-          admin_label: 'Delete relation link'
-          label: 'Link to delete Group content'
-          exclude: true
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          text: 'Delete relation'
-          entity_type: group_content
-          plugin_id: entity_link_delete
-        edit_node:
-          id: edit_node
-          table: node
-          field: edit_node
-          relationship: none
-          group_type: group
-          admin_label: 'Edit node link'
-          label: 'Link to edit Content'
-          exclude: true
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          text: 'Edit node'
-          entity_type: node
-          plugin_id: entity_link_edit
-        delete_node:
-          id: delete_node
-          table: node
-          field: delete_node
-          relationship: none
-          group_type: group
-          admin_label: 'Delete node link'
-          label: 'Link to delete Content'
-          exclude: true
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          text: 'Delete node'
-          entity_type: node
-          plugin_id: entity_link_delete
-        dropbutton:
-          id: dropbutton
-          table: views
-          field: dropbutton
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: Operations
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          fields:
-            view_group_content: view_group_content
-            edit_group_content: edit_group_content
-            delete_group_content: delete_group_content
-            edit_node: edit_node
-            delete_node: delete_node
-            title: '0'
-            type: '0'
-            status: '0'
-            changed: '0'
-          destination: true
-          plugin_id: dropbutton
-      filters:
-        status:
-          id: status
-          table: node_field_data
-          field: status
-          relationship: none
-          group_type: group
-          admin_label: ''
-          operator: '='
-          value: false
-          group: 1
-          exposed: true
-          expose:
-            operator_id: ''
-            label: 'Published status'
-            description: ''
-            use_operator: false
-            operator: status_op
-            identifier: status
-            required: true
-            remember: false
-            multiple: false
-            remember_roles:
-              authenticated: authenticated
-              anonymous: '0'
-              administrator: '0'
-              group_admin: '0'
-          is_grouped: true
-          group_info:
-            label: 'Published status'
-            description: ''
-            identifier: status
-            optional: true
-            widget: select
-            multiple: false
-            remember: false
-            default_group: All
-            default_group_multiple: {  }
-            group_items:
-              1:
-                title: Published
-                operator: '='
-                value: '1'
-              2:
-                title: Unpublished
-                operator: '='
-                value: '0'
-          entity_type: node
-          entity_field: status
-          plugin_id: boolean
-        type:
-          id: type
-          table: node_field_data
-          field: type
-          relationship: none
-          group_type: group
-          admin_label: ''
-          operator: in
-          value: {  }
-          group: 1
-          exposed: true
-          expose:
-            operator_id: type_op
-            label: Type
-            description: ''
-            use_operator: false
-            operator: type_op
-            identifier: type
-            required: false
-            remember: false
-            multiple: false
-            remember_roles:
-              authenticated: authenticated
-              anonymous: '0'
-              administrator: '0'
-              group_admin: '0'
-            reduce: false
-          is_grouped: false
-          group_info:
-            label: ''
-            description: ''
-            identifier: ''
-            optional: true
-            widget: select
-            multiple: false
-            remember: false
-            default_group: All
-            default_group_multiple: {  }
-            group_items: {  }
-          entity_type: node
-          entity_field: type
-          plugin_id: bundle
-      sorts: {  }
-      header: {  }
-      footer: {  }
-      empty:
-        area_text_custom:
-          id: area_text_custom
-          table: views
-          field: area_text_custom
-          relationship: none
-          group_type: group
-          admin_label: ''
-          empty: true
-          tokenize: false
-          content: 'No content available.'
-          plugin_id: text_custom
-      relationships:
-        group_content:
-          id: group_content
-          table: node_field_data
-          field: group_content
-          relationship: none
-          group_type: group
-          admin_label: 'Content relation'
-          required: true
-          group_content_plugins: {  }
-          entity_type: node
-          plugin_id: group_content_to_entity_reverse
-      arguments:
-        gid:
-          id: gid
-          table: group_content_field_data
-          field: gid
-          relationship: group_content
-          group_type: group
-          admin_label: ''
-          default_action: 'access denied'
-          exception:
-            value: all
-            title_enable: false
-            title: All
-          title_enable: true
-          title: '{{ arguments.gid|placeholder }} nodes'
-          default_argument_type: fixed
-          default_argument_options:
-            argument: ''
-          default_argument_skip_url: false
-          summary_options:
-            base_path: ''
-            count: true
-            items_per_page: 25
-            override: false
-          summary:
-            sort_order: asc
-            number_of_records: 0
-            format: default_summary
-          specify_validation: false
-          validate:
-            type: none
-            fail: 'not found'
-          validate_options: {  }
-          break_phrase: false
-          not: false
-          entity_type: group_content
-          entity_field: gid
-          plugin_id: numeric
-      display_extenders: {  }
-      title: Nodes
-    cache_metadata:
-      max-age: 0
-      contexts:
-        - group_membership.roles.permissions
-        - 'languages:language_content'
-        - 'languages:language_interface'
-        - url
-        - url.query_args
-        - 'user.node_grants:view'
-      tags: {  }
-  page_1:
-    display_plugin: page
-    id: page_1
-    display_title: Page
-    position: 1
-    display_options:
-      display_extenders: {  }
-      path: group/%group/nodes
-      menu:
-        type: tab
-        title: Nodes
-        description: ''
-        expanded: false
-        parent: ''
-        weight: 25
-        context: '0'
-        menu_name: main
-        enabled: true
-    cache_metadata:
-      max-age: 0
-      contexts:
-        - group_membership.roles.permissions
-        - 'languages:language_content'
-        - 'languages:language_interface'
-        - url
-        - url.query_args
-        - 'user.node_grants:view'
-      tags: {  }
diff --git a/web/modules/group/modules/gnode/gnode.group.permissions.yml b/web/modules/group/modules/gnode/gnode.group.permissions.yml
deleted file mode 100644
index 318a1d22ef..0000000000
--- a/web/modules/group/modules/gnode/gnode.group.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-access group_node overview:
-  title: 'Access group node overview'
-  description: 'Access the overview of all group nodes, regardless of node type'
diff --git a/web/modules/group/modules/gnode/gnode.info.yml b/web/modules/group/modules/gnode/gnode.info.yml
deleted file mode 100644
index 24529ec162..0000000000
--- a/web/modules/group/modules/gnode/gnode.info.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: 'Group Node'
-description: 'Enables Group functionality for the Node module'
-package: 'Group'
-type: 'module'
-# version: 1.0
-# core: '8.x'
-dependencies:
-  - 'node'
-  - 'group'
-
-# Information added by Drupal.org packaging script on 2017-02-20
-version: '8.x-1.0-beta5'
-core: '8.x'
-project: 'group'
-datestamp: 1487606183
diff --git a/web/modules/group/modules/gnode/gnode.install b/web/modules/group/modules/gnode/gnode.install
deleted file mode 100644
index 5422f03ae9..0000000000
--- a/web/modules/group/modules/gnode/gnode.install
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-
-/**
- * @file
- * Install, update and uninstall functions for the group node module.
- */
-
-use Drupal\Core\Config\ExtensionInstallStorage;
-use Drupal\Core\Config\InstallStorage;
-
-/**
- * Update the group nodes view to use the argument provided title.
- */
-function gnode_update_8001() {
-  if (\Drupal::moduleHandler()->moduleExists('views')) {
-    $view = \Drupal::configFactory()->getEditable('views.view.group_nodes');
-    if (!$view->isNew()) {
-      $view->set('display.default.display_options.title', 'Nodes');
-      $view->set('display.default.display_options.arguments.gid.title_enable', TRUE);
-      $view->set('display.default.display_options.arguments.gid.title', '{{ arguments.gid|placeholder }} nodes');
-      $view->save(TRUE);
-    }
-  }
-}
-
-/**
- * Update the group nodes view to use the access overview permission.
- */
-function gnode_update_8002() {
-  if (\Drupal::moduleHandler()->moduleExists('views')) {
-    $view = \Drupal::configFactory()->getEditable('views.view.group_nodes');
-    if (!$view->isNew()) {
-      $view->set('display.default.display_options.access.type', 'group_permission');
-      $view->set('display.default.display_options.access.options.group_permission', 'access group_node overview');
-      $view->save(TRUE);
-    }
-  }
-}
-
-/**
- * Make sure the views.view.group_nodes exists and fix broken copies.
- */
-function gnode_update_8003() {
-  $message = NULL;
-
-  $name = 'views.view.group_nodes';
-  $view = \Drupal::configFactory()->getEditable($name);
-
-  // Only update or insert the view if the Views module is enabled.
-  if (\Drupal::moduleHandler()->moduleExists('views')) {
-    $save_from_yaml = FALSE;
-
-    // If the view does not exist yet, we create it.
-    if ($view->isNew()) {
-      $save_from_yaml = TRUE;
-      $message = 'The view did not exist yet and has therefore been created.';
-    }
-    // We did not properly add the view in previous update functions, but did
-    // add keys to it, assuming the view existed. We should be able to find the
-    // broken views by checking for the absence of an ID.
-    elseif (!$view->get('id')) {
-      $save_from_yaml = TRUE;
-      $message = 'The view was broken by previous update hooks and has now been fixed.';
-    }
-
-    // If we flagged the view to be saved from the YAML definition, do so.
-    if ($save_from_yaml) {
-      // Get the storage for optional extension configuration.
-      $optional_storage = new ExtensionInstallStorage(
-        \Drupal::service('config.storage'),
-        InstallStorage::CONFIG_OPTIONAL_DIRECTORY
-      );
-
-      // Read the data from the YAML file and save it to the view.
-      $view->setData($optional_storage->read($name));
-      $view->save(TRUE);
-    }
-    else {
-      $message = 'The view was present and working as intended. Did nothing.';
-    }
-  }
-  // Otherwise delete the view if it exists in the storage.
-  elseif (!$view->isNew()) {
-    $view->delete();
-    $message = 'The view had been added even though the Views module is not installed. Removed the view.';
-  }
-
-  return $message;
-}
-
-/**
- * Use the new generic group permission names.
- */
-function gnode_update_8004() {
-  $config_factory = \Drupal::configFactory();
-
-  foreach ($config_factory->listAll('group.role.') as $group_role_config_name) {
-    $group_role = $config_factory->getEditable($group_role_config_name);
-
-    // Replace 'OP TYPE node' with 'OP group_node:TYPE entity'.
-    $search = '%^((?:\S+)(?: own| any)?) (\S+) node$%';
-    $replace = '$1 group_node:$2 entity';
-
-    $permissions = $group_role->get('permissions');
-    foreach ($permissions as &$permission) {
-      $permission = preg_replace($search, $replace, $permission);
-    }
-
-    $group_role->set('permissions', $permissions);
-    $group_role->save();
-  }
-}
diff --git a/web/modules/group/modules/gnode/gnode.links.action.yml b/web/modules/group/modules/gnode/gnode.links.action.yml
deleted file mode 100644
index 95dd7b53f8..0000000000
--- a/web/modules/group/modules/gnode/gnode.links.action.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-group_content.group_node_relate_page:
-  route_name: 'entity.group_content.group_node_relate_page'
-  title: 'Relate node'
-  appears_on:
-    - 'view.group_nodes.page_1'
-
-group_content.group_node_add_page:
-  route_name: 'entity.group_content.group_node_add_page'
-  title: 'Create node'
-  appears_on:
-    - 'view.group_nodes.page_1'
diff --git a/web/modules/group/modules/gnode/gnode.module b/web/modules/group/modules/gnode/gnode.module
deleted file mode 100644
index d184243932..0000000000
--- a/web/modules/group/modules/gnode/gnode.module
+++ /dev/null
@@ -1,292 +0,0 @@
-<?php
-
-/**
- * @file
- * Enables Group functionality for the Node module.
- */
-
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupContentType;
-use Drupal\node\NodeInterface;
-use Drupal\node\NodeTypeInterface;
-
-// We need a grant ID for match-all access records.
-define('GNODE_MASTER_GRANT_ID', 1986);
-
-/**
- * Implements hook_ENTITY_TYPE_insert().
- */
-function gnode_node_type_insert(NodeTypeInterface $node_type) {
-  \Drupal::service('plugin.manager.group_content_enabler')->clearCachedDefinitions();
-}
-
-/**
- * Implements hook_node_access().
- *
- * When trying to view, update or delete a node it suffices to have the right to
- * do so in only one group the node belongs to. If you wish to prevent any such
- * action on your own terms, implement hook_node_access() in your module.
- */
-function gnode_node_access(NodeInterface $node, $op, AccountInterface $account) {
-  // We do not care about create access as we have our own wizard for that. Any
-  // operation aside from 'view', 'update' and 'delete' is also unsupported.
-  if (!in_array($op, ['view', 'update', 'delete'])) {
-    return AccessResult::neutral();
-  }
-
-  // Some modules, including the code in \Drupal\node\NodeForm::access() may
-  // check for 'view', 'update' or 'delete' access on new nodes, even though
-  // that makes little sense. We need to account for it to avoid crashes because
-  // we would otherwise query the DB with a non-existent node ID.
-  if ($node->isNew()) {
-    return AccessResult::neutral();
-  }
-
-  $plugin_id = 'group_node:' . $node->bundle();
-
-  // Only act if there are group content types for this node type.
-  $group_content_types = GroupContentType::loadByContentPluginId($plugin_id);
-  if (empty($group_content_types)) {
-    return AccessResult::neutral();
-  }
-
-  // Load all the group content for this node.
-  $group_contents = \Drupal::entityTypeManager()
-    ->getStorage('group_content')
-    ->loadByProperties([
-      'type' => array_keys($group_content_types),
-      'entity_id' => $node->id(),
-    ]);
-
-  // If the node does not belong to any group, we have nothing to say.
-  if (empty($group_contents)) {
-    return AccessResult::neutral();
-  }
-
-  /** @var \Drupal\group\Entity\GroupInterface[] $groups */
-  $groups = [];
-  foreach ($group_contents as $group_content) {
-    /** @var \Drupal\group\Entity\GroupContentInterface $group_content */
-    $group = $group_content->getGroup();
-    $groups[$group->id()] = $group;
-  }
-
-  // From this point on you need group to allow you to perform the requested
-  // operation. If you are not granted access for a node belonging to a group,
-  // you should be denied access instead.
-  switch ($op) {
-    case 'view':
-      foreach ($groups as $group) {
-        if ($node->isPublished()) {
-          if ($group->hasPermission("view $plugin_id entity", $account)) {
-            return AccessResult::allowed();
-          }
-        }
-        elseif ($group->hasPermission("view unpublished $plugin_id entity", $account)) {
-          return AccessResult::allowed();
-        }
-      }
-      break;
-
-    case 'update':
-    case 'delete':
-      foreach ($groups as $group) {
-        if ($group->hasPermission("$op any $plugin_id entity", $account)) {
-          return AccessResult::allowed();
-        }
-        elseif ($account->id() == $node->getOwnerId() && $group->hasPermission("$op own $plugin_id entity", $account)) {
-          return AccessResult::allowed();
-        }
-      }
-      break;
-  }
-
-  return AccessResult::forbidden();
-}
-
-/**
- * Implements hook_node_grants().
- *
- * We define the following grants:
- * - 'gnode:NODE_TYPE': Grants view access for this node type.
- * - 'gnode_unpublished:NODE_TYPE': Grants view access to unpublished nodes.
- * - 'gnode_author:UID:NODE_TYPE': Grants update or delete access to authors.
- * - 'gnode_bypass': Given to anyone with the 'bypass group access' permission.
- *
- * @see gnode_node_access_records()
- */
-function gnode_node_grants(AccountInterface $account, $op) {
-  // Provide the master grant for users who can bypass group access.
-  if ($account->hasPermission('bypass group access')) {
-    return ['gnode_bypass' => [GNODE_MASTER_GRANT_ID]];
-  }
-
-  // Gather the machine names of all node types.
-  $entity_type_manager = \Drupal::entityTypeManager();
-  $node_type_ids = $entity_type_manager
-    ->getStorage('node_type')
-    ->getQuery()
-    ->execute();
-
-  // Initialize a grant array for members and one for anonymous/outsider users.
-  $grants_m = $grants_ao = [];
-
-  // If the user could not bypass group access, we need to check their access
-  // for every single group. Because loading every group would incur a massive
-  // performance hit, we only load those groups the user is a member of.
-  /** @var \Drupal\group\GroupMembershipLoaderInterface $membership_loader */
-  $membership_loader = \Drupal::service('group.membership_loader');
-  foreach ($membership_loader->loadByUser($account) as $group_membership) {
-    $group = $group_membership->getGroup();
-
-    // Add the groups the user is a member of to use later on.
-    $member_gids[] = $gid = $group->id();
-
-    foreach ($node_type_ids as $node_type_id) {
-      $plugin_id = "group_node:$node_type_id";
-
-      switch ($op) {
-        case 'view':
-          if ($group->hasPermission("view $plugin_id entity", $account)) {
-            $grants_m["gnode:$node_type_id"][] = $gid;
-          }
-          elseif ($group->hasPermission("view unpublished $plugin_id entity", $account)) {
-            $grants_m["gnode_unpublished:$node_type_id"][] = $gid;
-          }
-          break;
-
-        case 'update':
-        case 'delete':
-          // If you can act on any node, there's no need for the author grant.
-          if ($group->hasPermission("$op any $plugin_id entity", $account)) {
-            $grants_m["gnode:$node_type_id"][] = $gid;
-          }
-          elseif ($group->hasPermission("$op own $plugin_id entity", $account)) {
-            $uid = $account->id();
-            $grants_m["gnode_author:$uid:$node_type_id"][] = $gid;
-          }
-          break;
-      }
-    }
-  }
-
-  // All other groups have the benefit of sharing the same permission set among
-  // all anonymous or authenticated users per group type. We can therefore know
-  // the user's permissions for all groups of the same type they aren't part of.
-  /** @var \Drupal\group\Entity\GroupTypeInterface[] $group_types */
-  $group_types = $entity_type_manager->getStorage('group_type')->loadMultiple();
-  foreach ($group_types as $group_type) {
-    // Get the IDs of all the groups the user is not part of for the group type.
-    $query = $entity_type_manager->getStorage('group')->getQuery();
-    $query->condition('type', $group_type->id());
-    if (!empty($member_gids)) {
-      $query->condition('id', $member_gids, 'NOT IN');
-    }
-    $gids = $query->execute();
-
-    // If we could not retrieve any group IDs, skip to the next group type.
-    if (empty($gids)) {
-      continue;
-    }
-
-    // Grab the anonymous or outsider role for the group type depending on the
-    // user's account status (anonymous or authenticated).
-    $group_role = $account->isAnonymous()
-      ? $group_type->getAnonymousRole()
-      : $group_type->getOutsiderRole();
-
-    foreach ($node_type_ids as $node_type_id) {
-      $plugin_id = "group_node:$node_type_id";
-
-      // Only check for permissions if the group type has the group_node plugin
-      // installed for the node type.
-      if (!$group_type->hasContentPlugin($plugin_id)) {
-        continue;
-      }
-
-      switch ($op) {
-        case 'view':
-          if ($group_role->hasPermission("view $plugin_id entity")) {
-            $grants_ao["gnode:$node_type_id"] = $gids;
-          }
-          elseif ($group_role->hasPermission("view unpublished $plugin_id entity")) {
-            $grants_ao["gnode_unpublished:$node_type_id"] = $gids;
-          }
-          break;
-
-        case 'update':
-        case 'delete':
-          // If you can act on any node, there's no need for the author grant.
-          if ($group_role->hasPermission("$op any $plugin_id entity")) {
-            $grants_ao["gnode:$node_type_id"] = $gids;
-          }
-          elseif ($group_role->hasPermission("$op own $plugin_id entity")) {
-            $uid = $account->id();
-            $grants_ao["gnode_author:$uid:$node_type_id"] = $gids;
-          }
-          break;
-      }
-    }
-  }
-
-  // Recursively merge the member grants with the anonymous/outsider grants.
-  return array_merge_recursive($grants_m, $grants_ao);
-}
-
-/**
- * Implements hook_node_access_records().
- *
- * @see gnode_node_grants()
- */
-function gnode_node_access_records(NodeInterface $node) {
-  $records = [];
-  $type = $node->bundle();
-
-  // Only act if there are group content types for this node type.
-  $group_content_types = GroupContentType::loadByContentPluginId("group_node:$type");
-  if (empty($group_content_types)) {
-    return $records;
-  }
-
-  // Load all of the group content for this node.
-  $group_contents = \Drupal::entityTypeManager()
-    ->getStorage('group_content')
-    ->loadByProperties([
-      'type' => array_keys($group_content_types),
-      'entity_id' => $node->id()
-    ]);
-
-  // Only act if there are group content entities for this node.
-  if (empty($group_contents)) {
-    return $records;
-  }
-
-  // We can use the same grant-all base because we will only hand out the grants
-  // based on the $op parameter in hook_node_grants().
-  $base = [
-    'grant_view' => 1,
-    'grant_update' => 1,
-    'grant_delete' => 1,
-    'priority' => 0,
-  ];
-
-  // Set records for every group the node belongs to.
-  foreach ($group_contents as $group_content) {
-    /** @var \Drupal\group\Entity\GroupContentInterface $group_content */
-    $gid = $group_content->getGroup()->id();
-
-    // Add the non-author record for viewing nodes.
-    $prefix = $node->isPublished() ? 'gnode' : 'gnode_unpublished';
-    $records[] = ['gid' => $gid, 'realm' => "$prefix:$type"] + $base;
-
-    // Add the author record for updating or deleting.
-    $uid = $node->getOwnerId();
-    $records[] = ['gid' => $gid, 'realm' => "gnode_author:$uid:$type"] + $base;
-  }
-
-  // Add the general access bypass record.
-  $records[] = ['gid' => GNODE_MASTER_GRANT_ID, 'realm' => 'gnode_bypass'] + $base;
-
-  return $records;
-}
diff --git a/web/modules/group/modules/gnode/gnode.routing.yml b/web/modules/group/modules/gnode/gnode.routing.yml
deleted file mode 100644
index d247a79e03..0000000000
--- a/web/modules/group/modules/gnode/gnode.routing.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-route_callbacks:
-  - '\Drupal\gnode\Routing\GroupNodeRouteProvider::getRoutes'
diff --git a/web/modules/group/modules/gnode/src/Controller/GroupNodeController.php b/web/modules/group/modules/gnode/src/Controller/GroupNodeController.php
deleted file mode 100644
index 88122772c4..0000000000
--- a/web/modules/group/modules/gnode/src/Controller/GroupNodeController.php
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php
-
-namespace Drupal\gnode\Controller;
-
-use Drupal\Core\Entity\EntityFormBuilderInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Render\RendererInterface;
-use Drupal\group\Entity\Controller\GroupContentController;
-use Drupal\group\Entity\GroupInterface;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Drupal\user\PrivateTempStoreFactory;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Returns responses for 'group_node' GroupContent routes.
- */
-class GroupNodeController extends GroupContentController {
-
-  /**
-   * The group content plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * Constructs a new GroupNodeController.
-   *
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content plugin manager.
-   * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
-   *   The private store factory.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entity_form_builder
-   *   The entity form builder.
-   * @param \Drupal\Core\Render\RendererInterface $renderer
-   *   The renderer.
-   */
-  public function __construct(GroupContentEnablerManagerInterface $plugin_manager, PrivateTempStoreFactory $temp_store_factory, EntityTypeManagerInterface $entity_type_manager, EntityFormBuilderInterface $entity_form_builder, RendererInterface $renderer) {
-    parent::__construct($temp_store_factory, $entity_type_manager, $entity_form_builder, $renderer);
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('plugin.manager.group_content_enabler'),
-      $container->get('user.private_tempstore'),
-      $container->get('entity_type.manager'),
-      $container->get('entity.form_builder'),
-      $container->get('renderer')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function addPage(GroupInterface $group, $create_mode = FALSE) {
-    $build = parent::addPage($group, $create_mode);
-
-    // Do not interfere with redirects.
-    if (!is_array($build)) {
-      return $build;
-    }
-
-    // Overwrite the label and description for all of the displayed bundles.
-    $storage_handler = $this->entityTypeManager->getStorage('node_type');
-    foreach ($this->addPageBundles($group, $create_mode) as $plugin_id => $bundle_name) {
-      if (!empty($build['#bundles'][$bundle_name])) {
-        $plugin = $group->getGroupType()->getContentPlugin($plugin_id);
-        $bundle_label = $storage_handler->load($plugin->getEntityBundle())->label();
-
-        $t_args = ['%node_type' => $bundle_label];
-        $description = $create_mode
-          ? $this->t('Create a node of type %node_type in the group.', $t_args)
-          : $this->t('Add an existing node of type %node_type to the group.', $t_args);
-
-        $build['#bundles'][$bundle_name]['label'] = $bundle_label;
-        $build['#bundles'][$bundle_name]['description'] = $description;
-      }
-    }
-
-    return $build;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function addPageBundles(GroupInterface $group, $create_mode) {
-    $bundles = [];
-
-    // Retrieve all group_node plugins for the group's type.
-    $plugin_ids = $this->pluginManager->getInstalledIds($group->getGroupType());
-    foreach ($plugin_ids as $key => $plugin_id) {
-      if (strpos($plugin_id, 'group_node:') !== 0) {
-        unset($plugin_ids[$key]);
-      }
-    }
-
-    // Retrieve all of the responsible group content types, keyed by plugin ID.
-    $storage = $this->entityTypeManager->getStorage('group_content_type');
-    $properties = ['group_type' => $group->bundle(), 'content_plugin' => $plugin_ids];
-    foreach ($storage->loadByProperties($properties) as $bundle => $group_content_type) {
-      /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-      $bundles[$group_content_type->getContentPluginId()] = $bundle;
-    }
-
-    return $bundles;
-  }
-
-}
diff --git a/web/modules/group/modules/gnode/src/Plugin/GroupContentEnabler/GroupNode.php b/web/modules/group/modules/gnode/src/Plugin/GroupContentEnabler/GroupNode.php
deleted file mode 100644
index c8a59dd529..0000000000
--- a/web/modules/group/modules/gnode/src/Plugin/GroupContentEnabler/GroupNode.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-
-namespace Drupal\gnode\Plugin\GroupContentEnabler;
-
-use Drupal\group\Entity\GroupInterface;
-use Drupal\group\Plugin\GroupContentEnablerBase;
-use Drupal\node\Entity\NodeType;
-use Drupal\Core\Url;
-use Drupal\Core\Form\FormStateInterface;
-
-/**
- * Provides a content enabler for nodes.
- *
- * @GroupContentEnabler(
- *   id = "group_node",
- *   label = @Translation("Group node"),
- *   description = @Translation("Adds nodes to groups both publicly and privately."),
- *   entity_type_id = "node",
- *   entity_access = TRUE,
- *   pretty_path_key = "node",
- *   reference_label = @Translation("Title"),
- *   reference_description = @Translation("The title of the node to add to the group"),
- *   deriver = "Drupal\gnode\Plugin\GroupContentEnabler\GroupNodeDeriver"
- * )
- */
-class GroupNode extends GroupContentEnablerBase {
-
-  /**
-   * Retrieves the node type this plugin supports.
-   *
-   * @return \Drupal\node\NodeTypeInterface
-   *   The node type this plugin supports.
-   */
-  protected function getNodeType() {
-    return NodeType::load($this->getEntityBundle());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupOperations(GroupInterface $group) {
-    $account = \Drupal::currentUser();
-    $plugin_id = $this->getPluginId();
-    $type = $this->getEntityBundle();
-    $operations = [];
-
-    if ($group->hasPermission("create $plugin_id entity", $account)) {
-      $route_params = ['group' => $group->id(), 'plugin_id' => $plugin_id];
-      $operations["gnode-create-$type"] = [
-        'title' => $this->t('Create @type', ['@type' => $this->getNodeType()->label()]),
-        'url' => new Url('entity.group_content.create_form', $route_params),
-        'weight' => 30,
-      ];
-    }
-
-    return $operations;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getTargetEntityPermissions() {
-    $permissions = parent::getTargetEntityPermissions();
-    $plugin_id = $this->getPluginId();
-
-    // Add a 'view unpublished' permission by re-using most of the 'view' one.
-    $original = $permissions["view $plugin_id entity"];
-    $permissions["view unpublished $plugin_id entity"] = [
-      'title' => str_replace('View ', 'View unpublished ', $original['title']),
-    ] + $original;
-
-    return $permissions;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function defaultConfiguration() {
-    $config = parent::defaultConfiguration();
-    $config['entity_cardinality'] = 1;
-    return $config;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
-    $form = parent::buildConfigurationForm($form, $form_state);
-
-    // Disable the entity cardinality field as the functionality of this module
-    // relies on a cardinality of 1. We don't just hide it, though, to keep a UI
-    // that's consistent with other content enabler plugins.
-    $info = $this->t("This field has been disabled by the plugin to guarantee the functionality that's expected of it.");
-    $form['entity_cardinality']['#disabled'] = TRUE;
-    $form['entity_cardinality']['#description'] .= '<br /><em>' . $info . '</em>';
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function calculateDependencies() {
-    $dependencies = parent::calculateDependencies();
-    $dependencies['config'][] = 'node.type.' . $this->getEntityBundle();
-    return $dependencies;
-  }
-
-}
diff --git a/web/modules/group/modules/gnode/src/Plugin/GroupContentEnabler/GroupNodeDeriver.php b/web/modules/group/modules/gnode/src/Plugin/GroupContentEnabler/GroupNodeDeriver.php
deleted file mode 100644
index 744d2359ba..0000000000
--- a/web/modules/group/modules/gnode/src/Plugin/GroupContentEnabler/GroupNodeDeriver.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-namespace Drupal\gnode\Plugin\GroupContentEnabler;
-
-use Drupal\node\Entity\NodeType;
-use Drupal\Component\Plugin\Derivative\DeriverBase;
-
-class GroupNodeDeriver extends DeriverBase {
-
-  /**
-   * {@inheritdoc}.
-   */
-  public function getDerivativeDefinitions($base_plugin_definition) {
-    foreach (NodeType::loadMultiple() as $name => $node_type) {
-      $label = $node_type->label();
-
-      $this->derivatives[$name] = [
-        'entity_bundle' => $name,
-        'label' => t('Group node') . " ($label)",
-        'description' => t('Adds %type content to groups both publicly and privately.', ['%type' => $label]),
-      ] + $base_plugin_definition;
-    }
-
-    return $this->derivatives;
-  }
-
-}
diff --git a/web/modules/group/modules/gnode/src/Routing/GroupNodeRouteProvider.php b/web/modules/group/modules/gnode/src/Routing/GroupNodeRouteProvider.php
deleted file mode 100644
index 4d8c76a8cc..0000000000
--- a/web/modules/group/modules/gnode/src/Routing/GroupNodeRouteProvider.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-
-namespace Drupal\gnode\Routing;
-
-use Drupal\node\Entity\NodeType;
-use Symfony\Component\Routing\Route;
-
-/**
- * Provides routes for group_node group content.
- */
-class GroupNodeRouteProvider {
-
-  /**
-   * Provides the shared collection route for group node plugins.
-   */
-  public function getRoutes() {
-    $routes = $plugin_ids = $permissions_add = $permissions_create = [];
-
-    foreach (NodeType::loadMultiple() as $name => $node_type) {
-      $plugin_id = "group_node:$name";
-
-      $plugin_ids[] = $plugin_id;
-      $permissions_add[] = "create $plugin_id content";
-      $permissions_create[] = "create $plugin_id entity";
-    }
-
-    // If there are no node types yet, we cannot have any plugin IDs and should
-    // therefore exit early because we cannot have any routes for them either.
-    if (empty($plugin_ids)) {
-      return $routes;
-    }
-
-    $routes['entity.group_content.group_node_relate_page'] = new Route('group/{group}/node/add');
-    $routes['entity.group_content.group_node_relate_page']
-      ->setDefaults([
-        '_title' => 'Relate node',
-        '_controller' => '\Drupal\gnode\Controller\GroupNodeController::addPage',
-      ])
-      ->setRequirement('_group_permission', implode('+', $permissions_add))
-      ->setRequirement('_group_installed_content', implode('+', $plugin_ids))
-      ->setOption('_group_operation_route', TRUE);
-
-    $routes['entity.group_content.group_node_add_page'] = new Route('group/{group}/node/create');
-    $routes['entity.group_content.group_node_add_page']
-      ->setDefaults([
-        '_title' => 'Create node',
-        '_controller' => '\Drupal\gnode\Controller\GroupNodeController::addPage',
-        'create_mode' => TRUE,
-      ])
-      ->setRequirement('_group_permission', implode('+', $permissions_create))
-      ->setRequirement('_group_installed_content', implode('+', $plugin_ids))
-      ->setOption('_group_operation_route', TRUE);
-
-    return $routes;
-  }
-
-}
diff --git a/web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeAccessRecordsTest.php b/web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeAccessRecordsTest.php
deleted file mode 100644
index 10607ca664..0000000000
--- a/web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeAccessRecordsTest.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-
-namespace Drupal\Tests\gnode\Kernel;
-
-/**
- * Tests the access records that are set for group nodes.
- *
- * @group gnode
- */
-class GroupNodeAccessRecordsTest extends GroupNodeAccessTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->installSchema('node', 'node_access');
-  }
-
-  /**
-   * Tests that no access records are set for ungrouped nodes.
-   */
-  public function testUngroupedNode() {
-    $node = $this->entityTypeManager
-      ->getStorage('node')
-      ->create([
-        'type' => 'a',
-        'title' => $this->randomMachineName(),
-      ]);
-    $node->save();
-
-    $records = gnode_node_access_records($node);
-    $this->assertEmpty($records, 'No access records set for an ungrouped node.');
-  }
-
-  /**
-   * Tests the access records for a published group node.
-   */
-  public function testPublishedGroupNode() {
-    /** @var \Drupal\node\NodeInterface $node */
-    $node = $this->entityTypeManager
-      ->getStorage('node')
-      ->create([
-        'type' => 'a',
-        'title' => $this->randomMachineName(),
-      ]);
-    $node->save();
-    $this->groupA1->addContent($node, 'group_node:a');
-
-    $records = gnode_node_access_records($node);
-    $this->assertCount(3, $records, '3 access records set for a published group node.');
-
-    $base = [
-      'grant_view' => 1,
-      'grant_update' => 1,
-      'grant_delete' => 1,
-      'priority' => 0,
-    ];
-    $gid = $this->groupA1->id();
-    $uid = $node->getOwnerId();
-    $this->assertEquals(['gid' => $gid, 'realm' => 'gnode:a'] + $base, $records[0], 'General gnode:NODE_TYPE grant found.');
-    $this->assertEquals(['gid' => $gid, 'realm' => "gnode_author:$uid:a"] + $base, $records[1], 'Author gnode_author:UID:NODE_TYPE grant found.');
-    $this->assertEquals(['gid' => GNODE_MASTER_GRANT_ID, 'realm' => 'gnode_bypass'] + $base, $records[2], 'Admin gnode_bypass grant found.');
-  }
-
-  /**
-   * Tests the access records for an unpublished group node.
-   */
-  public function testUnpublishedGroupNode() {
-    /** @var \Drupal\node\NodeInterface $node */
-    $node = $this->entityTypeManager
-      ->getStorage('node')
-      ->create([
-        'type' => 'a',
-        'title' => $this->randomMachineName(),
-        'status' => NODE_NOT_PUBLISHED,
-      ]);
-    $node->save();
-    $this->groupA1->addContent($node, 'group_node:a');
-
-    $records = gnode_node_access_records($node);
-    $this->assertCount(3, $records, '3 access records set for an unpublished group node.');
-
-    $base = [
-      'grant_view' => 1,
-      'grant_update' => 1,
-      'grant_delete' => 1,
-      'priority' => 0,
-    ];
-    $gid = $this->groupA1->id();
-    $uid = $node->getOwnerId();
-    $this->assertEquals(['gid' => $gid, 'realm' => 'gnode_unpublished:a'] + $base, $records[0], 'General gnode_unpublished:NODE_TYPE grant found.');
-    $this->assertEquals(['gid' => $gid, 'realm' => "gnode_author:$uid:a"] + $base, $records[1], 'Author gnode_author:UID:NODE_TYPE grant found.');
-    $this->assertEquals(['gid' => GNODE_MASTER_GRANT_ID, 'realm' => 'gnode_bypass'] + $base, $records[2], 'Admin gnode_bypass grant found.');
-  }
-
-}
diff --git a/web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeAccessTestBase.php b/web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeAccessTestBase.php
deleted file mode 100644
index 62c2996be3..0000000000
--- a/web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeAccessTestBase.php
+++ /dev/null
@@ -1,157 +0,0 @@
-<?php
-
-namespace Drupal\Tests\gnode\Kernel;
-
-use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
-
-/**
- * Test base for testing access records and grants for group nodes.
- */
-abstract class GroupNodeAccessTestBase extends EntityKernelTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['group', 'node', 'gnode'];
-
-  /**
-   * The entity type manager service.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The account to use for retrieving the grants.
-   *
-   * @var \Drupal\Core\Session\AccountInterface
-   */
-  protected $account;
-
-  /**
-   * A dummy group type with ID 'a'.
-   *
-   * @var \Drupal\group\Entity\GroupTypeInterface
-   */
-  protected $groupTypeA;
-
-  /**
-   * A dummy group type with ID 'b'.
-   *
-   * @var \Drupal\group\Entity\GroupTypeInterface
-   */
-  protected $groupTypeB;
-
-  /**
-   * A dummy group of type 'a' with the test account as a member.
-   *
-   * @var \Drupal\group\Entity\GroupInterface
-   */
-  protected $groupA1;
-
-  /**
-   * A dummy group of type 'a' with the test account as an outsider.
-   *
-   * @var \Drupal\group\Entity\GroupInterface
-   */
-  protected $groupA2;
-
-  /**
-   * A dummy group of type 'b' with the test account as a member.
-   *
-   * @var \Drupal\group\Entity\GroupInterface
-   */
-  protected $groupB1;
-
-  /**
-   * A dummy group of type 'b' with the test account as an outsider.
-   *
-   * @var \Drupal\group\Entity\GroupInterface
-   */
-  protected $groupB2;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->entityTypeManager = $this->container->get('entity_type.manager');
-
-    $this->installConfig(['group', 'node']);
-    $this->installEntitySchema('group');
-    $this->installEntitySchema('group_type');
-    $this->installEntitySchema('group_content');
-    $this->installEntitySchema('group_content_type');
-
-    // Create the test user account.
-    $this->account = $this->createUser(['uid' => 2]);
-
-    // Create some group types.
-    $storage = $this->entityTypeManager->getStorage('group_type');
-    $values = ['label' => 'foo', 'description' => 'bar'];
-    $this->groupTypeA = $storage->create(['id' => 'a'] + $values);
-    $this->groupTypeB = $storage->create(['id' => 'b'] + $values);
-    $this->groupTypeA->save();
-    $this->groupTypeB->save();
-
-    // Create some node types.
-    $storage = $this->entityTypeManager->getStorage('node_type');
-    $values = ['name' => 'foo', 'description' => 'bar'];
-    $storage->create(['type' => 'a'] + $values)->save();
-    $storage->create(['type' => 'b'] + $values)->save();
-    $storage->create(['type' => 'c'] + $values)->save();
-
-    // Install some node types on some group types.
-    /** @var \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface $storage */
-    $storage = $this->entityTypeManager->getStorage('group_content_type');
-    $storage->createFromPlugin($this->groupTypeA, 'group_node:a')->save();
-    $storage->createFromPlugin($this->groupTypeA, 'group_node:b')->save();
-    $storage->createFromPlugin($this->groupTypeB, 'group_node:b')->save();
-
-    // Set group_node permissions on the group types.
-    $member_a = [
-      'view group_node:a entity',
-      'view group_node:b entity',
-      'update own group_node:a entity',
-      'delete own group_node:a entity',
-    ];
-    $member_b = [
-      'update any group_node:b entity',
-      'delete any group_node:b entity',
-    ];
-    $outsider_a = [
-      'view group_node:a entity',
-      'update any group_node:a entity',
-      'delete any group_node:a entity',
-    ];
-    $outsider_b = [
-      'view group_node:b entity',
-      'update own group_node:b entity',
-      'delete own group_node:b entity',
-    ];
-    $this->groupTypeA->getMemberRole()->grantPermissions($member_a)->save();
-    $this->groupTypeB->getMemberRole()->grantPermissions($member_b)->save();
-    $this->groupTypeA->getOutsiderRole()->grantPermissions($outsider_a)->save();
-    $this->groupTypeB->getOutsiderRole()->grantPermissions($outsider_b)->save();
-
-    // Create some groups.
-    $storage = $this->entityTypeManager->getStorage('group');
-    $values = ['uid' => $this->account->id(), 'label' => 'foo'];
-    $this->groupA1 = $storage->create(['type' => 'a'] + $values);
-    $this->groupA2 = $storage->create(['type' => 'a'] + $values);
-    $this->groupB1 = $storage->create(['type' => 'b'] + $values);
-    $this->groupB2 = $storage->create(['type' => 'b'] + $values);
-    $this->groupA1->save();
-    $this->groupA2->save();
-    $this->groupB1->save();
-    $this->groupB2->save();
-
-    // Remove the test account from the A2 and B2 groups.
-    $this->groupA2->removeMember($this->account);
-    $this->groupB2->removeMember($this->account);
-  }
-
-}
diff --git a/web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeGrantsTest.php b/web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeGrantsTest.php
deleted file mode 100644
index 594d1793e0..0000000000
--- a/web/modules/group/modules/gnode/tests/src/Kernel/GroupNodeGrantsTest.php
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-
-namespace Drupal\Tests\gnode\Kernel;
-
-/**
- * Tests the grants people receive for group nodes.
- *
- * @group gnode
- */
-class GroupNodeGrantsTest extends GroupNodeAccessTestBase {
-
-  /**
-   * Tests the assignment of the bypass access grant.
-   */
-  public function testBypassGrant() {
-    $account = $this->createUser([], ['bypass group access']);
-    $grants = gnode_node_grants($account, 'view');
-    $this->assertEquals(['gnode_bypass' => [GNODE_MASTER_GRANT_ID]], $grants, 'Users who can bypass group access receive the bypass grant.');
-  }
-
-  /**
-   * Tests the existence of specific grant realms.
-   */
-  public function testGrantRealms() {
-    $grants = gnode_node_grants($this->account, 'view');
-    $this->assertArrayHasKey('gnode:a', $grants, 'Grants were handed out for node type a.');
-    $this->assertArrayHasKey('gnode:b', $grants, 'Grants were handed out for node type b.');
-    $this->assertArrayNotHasKey('gnode:c', $grants, 'Grants were not handed out for node type c.');
-  }
-
-  /**
-   * Tests that a user receives the right view grants for group nodes.
-   */
-  public function testViewGrants() {
-    $grants = gnode_node_grants($this->account, 'view');
-    $this->assertTrue(in_array($this->groupA1->id(), $grants['gnode:a']), 'A-group: Member can view A-nodes.');
-    $this->assertTrue(in_array($this->groupA1->id(), $grants['gnode:b']), 'A-group: Member can view B-nodes.');
-    $this->assertTrue(in_array($this->groupA2->id(), $grants['gnode:a']), 'A-group: Outsider can view A-nodes.');
-    $this->assertTrue(in_array($this->groupB2->id(), $grants['gnode:b']), 'B-group: Outsider can view B-nodes.');
-
-    // We are testing a bit more specifically here to make sure that the system
-    // is only adding those group IDs the user has access in. Seeing as further
-    // tests rely on the same system, we are not testing this again.
-    $this->assertFalse(in_array($this->groupA2->id(), $grants['gnode:b']), 'A-group: Outsider can not view B-nodes.');
-    $this->assertFalse(in_array($this->groupB1->id(), $grants['gnode:b']), 'B-group: Member can not view B-nodes.');
-  }
-
-  /**
-   * Tests that a user receives the right update grants for group nodes.
-   */
-  public function testUpdateGrants() {
-    $grants = gnode_node_grants($this->account, 'update');
-
-    // Test 'update any' permissions.
-    $this->assertTrue(in_array($this->groupA2->id(), $grants['gnode:a']), 'A-group: Outsider can update any A-nodes.');
-    $this->assertTrue(in_array($this->groupB1->id(), $grants['gnode:b']), 'B-group: Member can update any B-nodes.');
-
-    // Test 'update own' permissions.
-    $this->assertTrue(in_array($this->groupA1->id(), $grants['gnode_author:2:a']), 'A-group: Member can update own A-nodes.');
-    $this->assertTrue(in_array($this->groupB2->id(), $grants['gnode_author:2:b']), 'B-group: Outsider can update own B-nodes.');
-  }
-
-  /**
-   * Tests that a user receives the right delete grants for group nodes.
-   */
-  public function testDeleteGrants() {
-    $grants = gnode_node_grants($this->account, 'delete');
-
-    // Test 'delete any' permissions.
-    $this->assertTrue(in_array($this->groupA2->id(), $grants['gnode:a']), 'A-group: Outsider can delete any A-nodes.');
-    $this->assertTrue(in_array($this->groupB1->id(), $grants['gnode:b']), 'B-group: Member can delete any B-nodes.');
-
-    // Test 'delete own' permissions.
-    $this->assertTrue(in_array($this->groupA1->id(), $grants['gnode_author:2:a']), 'A-group: Member can delete own A-nodes.');
-    $this->assertTrue(in_array($this->groupB2->id(), $grants['gnode_author:2:b']), 'B-group: Outsider can delete own B-nodes.');
-  }
-
-}
diff --git a/web/modules/group/modules/grolesync/grolesync.info.yml b/web/modules/group/modules/grolesync/grolesync.info.yml
deleted file mode 100644
index 8b0733b2f9..0000000000
--- a/web/modules/group/modules/grolesync/grolesync.info.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: 'Group role sync'
-description: 'DOES NOT CURRENTLY WORK, SEE https://www.drupal.org/node/2850417. Allows you to synchronize global roles to group roles.'
-package: 'Group (Work in progress)'
-type: 'module'
-# version: 1.0
-# core: '8.x'
-dependencies:
-  - 'user'
-  - 'group'
-
-# Information added by Drupal.org packaging script on 2017-02-20
-version: '8.x-1.0-beta5'
-core: '8.x'
-project: 'group'
-datestamp: 1487606183
diff --git a/web/modules/group/modules/grolesync/grolesync.links.task.yml b/web/modules/group/modules/grolesync/grolesync.links.task.yml
deleted file mode 100644
index cc791478fd..0000000000
--- a/web/modules/group/modules/grolesync/grolesync.links.task.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-#group_type.permissions_form.basic:
-#  title: 'Group roles'
-#  route_name: 'entity.group_type.permissions_form'
-#  base_route: 'entity.group_type.edit_form'
-#  parent_id: 'group_type.permissions_form'
-
-#group_type.role_sync_form:
-#  title: 'Synchronized roles'
-#  route_name: 'entity.group_type.grolesync'
-#  base_route: 'entity.group_type.edit_form'
-#  parent_id: 'group_type.permissions_form'
-#  weight: 5
diff --git a/web/modules/group/modules/grolesync/grolesync.module b/web/modules/group/modules/grolesync/grolesync.module
deleted file mode 100644
index 611e40000d..0000000000
--- a/web/modules/group/modules/grolesync/grolesync.module
+++ /dev/null
@@ -1,86 +0,0 @@
-<?php
-
-/**
- * @file
- * Allows you to synchronize global roles to special 'outsider' group roles.
- */
-
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Url;
-use Drupal\User\RoleInterface;
-use Drupal\group\Entity\GroupTypeInterface;
-
-/**
- * Gets the group role synchronizer service.
- *
- * @return \Drupal\grolesync\GroupRoleSynchronizerInterface
- *   The group role synchronizer service.
- *
- * @internal Try to properly inject the service when possible.
- */
-function _grolesync_synchronizer() {
-  return \Drupal::service('grolesync.synchronizer');
-}
-
-/**
- * Implements hook_rebuild().
- */
-function grolesync_rebuild() {
-  //_grolesync_synchronizer()->createGroupRoles();
-}
-
-/**
- * Implements hook_modules_installed().
- */
-function grolesync_modules_installed($modules) {
-  //_grolesync_synchronizer()->createGroupRoles();
-}
-
-/**
- * Implements hook_ENTITY_TYPE_insert().
- */
-function grolesync_group_type_insert(GroupTypeInterface $group_type) {
-  //_grolesync_synchronizer()->createGroupRoles([$group_type->id()]);
-}
-
-/**
- * Implements hook_ENTITY_TYPE_insert().
- */
-function grolesync_user_role_insert(RoleInterface $role) {
-  //_grolesync_synchronizer()->createGroupRoles(NULL, [$role->id()]);
-}
-
-/**
- * Implements hook_ENTITY_TYPE_update().
- */
-function grolesync_user_role_update(RoleInterface $role) {
-  /** @var \Drupal\User\RoleInterface $original */
-  /*$original = $role->original;
-
-  // Update the group roles if the user role label changed.
-  if ($role->label() != $original->label()) {
-    _grolesync_synchronizer()->updateGroupRoleLabels($role);
-  }*/
-}
-
-/**
- * Implements hook_entity_operation().
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- *   The entity on which the linked operations will be performed.
- *
- * @return array
- */
-function grolesync_entity_operation(EntityInterface $entity) {
-  /*$operations = [];
-
-  if ($entity->getEntityTypeId() == 'group_type') {
-    $operations['synchronized-roles'] = array(
-      'title' => t('Synchronized roles'),
-      'url' => Url::fromRoute('entity.group_type.grolesync', ['group_type' => $entity->id()]),
-      'weight' => 43,
-    );
-  }
-
-  return $operations;*/
-}
diff --git a/web/modules/group/modules/grolesync/grolesync.routing.yml b/web/modules/group/modules/grolesync/grolesync.routing.yml
deleted file mode 100644
index 786bf9b156..0000000000
--- a/web/modules/group/modules/grolesync/grolesync.routing.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-#entity.group_type.grolesync:
-#  path: '/admin/group/types/manage/{group_type}/rolesync'
-#  defaults:
-#    _form: '\Drupal\grolesync\Form\GroupRoleSyncForm'
-#    _title: 'Synchronized roles'
-#  requirements:
-#    _permission: 'administer group'
diff --git a/web/modules/group/modules/grolesync/grolesync.services.yml b/web/modules/group/modules/grolesync/grolesync.services.yml
deleted file mode 100644
index 5050c5663b..0000000000
--- a/web/modules/group/modules/grolesync/grolesync.services.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-#services:
-#  grolesync.synchronizer:
-#    class: 'Drupal\grolesync\GroupRoleSynchronizer'
-#    arguments: ['@entity_type.manager']
diff --git a/web/modules/group/modules/grolesync/src/Form/GroupRoleSyncForm.php b/web/modules/group/modules/grolesync/src/Form/GroupRoleSyncForm.php
deleted file mode 100644
index 14bfe00287..0000000000
--- a/web/modules/group/modules/grolesync/src/Form/GroupRoleSyncForm.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-namespace Drupal\grolesync\Form;
-
-use Drupal\group\Form\GroupPermissionsTypeSpecificForm;
-
-/**
- * Provides the roles synchronization form for a specific group type.
- */
-class GroupRoleSyncForm extends GroupPermissionsTypeSpecificForm {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getInfo() {
-    $info = [
-      'sync_info' => [
-        '#prefix' => '<p>',
-        '#suffix' => '</p>',
-        '#markup' => $this->t("Below you can assign group permissions to global site roles.<br />Anyone with any of those roles will automatically receive the selected permissions, even if they are not a member of the group."),
-      ],
-      'audience_info' => [
-        '#prefix' => '<p>',
-        '#suffix' => '</p>',
-        '#markup' => $this->t('Please note that the permissions available for configuration are those you would normally be able to assign to the <em>Outsider</em> role.<br />If you need to vary permissions for members, you should create a group role under the <em>Roles</em> tab instead.'),
-      ],
-    ] + parent::getInfo();
-
-    // Unset the info about the group role audiences.
-    unset($info['role_info']);
-
-    return $info;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getGroupRoles() {
-    $properties = [
-      'group_type' => $this->groupType->id(),
-      'permissions_ui' => FALSE,
-    ];
-
-    /** @var \Drupal\group\Entity\GroupRoleInterface[] $group_roles */
-    $group_roles = $this->entityTypeManager->getStorage('group_role')->loadByProperties($properties);
-
-    // Synchronized group roles are saved with an enforced dependency on this
-    // module. The easiest way to find those that we need to show, is to load
-    // all "hidden" group roles for this group type and check the dependencies.
-    foreach ($group_roles as $group_role_id => $group_role) {
-      $dependencies = $group_role->getDependencies();
-      if (!isset($dependencies['module']) || !in_array('grolesync', $dependencies['module'])) {
-        unset($group_roles[$group_role_id]);
-      }
-    }
-
-    return $group_roles;
-  }
-
-}
diff --git a/web/modules/group/modules/grolesync/src/GroupRoleSynchronizer.php b/web/modules/group/modules/grolesync/src/GroupRoleSynchronizer.php
deleted file mode 100644
index 49aa98a807..0000000000
--- a/web/modules/group/modules/grolesync/src/GroupRoleSynchronizer.php
+++ /dev/null
@@ -1,140 +0,0 @@
-<?php
-
-namespace Drupal\grolesync;
-
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\group\Entity\GroupRole;
-use Drupal\group\Entity\GroupTypeInterface;
-use Drupal\User\RoleInterface;
-
-/**
- * Synchronizes user roles to group roles.
- */
-class GroupRoleSynchronizer implements GroupRoleSynchronizerInterface {
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * Constructs a new GroupRoleSynchronizer.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
-    $this->entityTypeManager = $entity_type_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupRoleId($group_type_id, $role_id) {
-    // The maximum length of a group role's machine name.
-    //
-    // Group role IDs consist of two parts separated by a dash:
-    // - The group type ID.
-    // - The machine name of the group role; unique per group type.
-    //
-    // Therefore, the maximum length of a group role machine name is determined
-    // by subtracting the group type ID length from the entity type ID length
-    // and leaving room for a dash character.
-    $machine_name_max_length = EntityTypeInterface::ID_MAX_LENGTH - GroupTypeInterface::ID_MAX_LENGTH - 1;
-
-    // Generate an MD5 hash to use as the group role machine name.
-    $machine_name = substr(md5('group_role_sync.' . $role_id), 0, $machine_name_max_length);
-
-    return "$group_type_id-$machine_name";
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function createGroupRoles($group_type_ids = NULL, $role_ids = NULL) {
-    /** @var \Drupal\group\Entity\GroupTypeInterface[] $group_types */
-    $group_types = $this->entityTypeManager->getStorage('group_type')->loadMultiple($group_type_ids);
-
-    // Return early if there are no group types to create roles for.
-    if (empty($group_types)) {
-      return;
-    }
-
-    /** @var \Drupal\User\RoleInterface[] $user_roles */
-    $user_roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple($role_ids);
-
-    $definitions = [];
-    foreach (array_keys($user_roles) as $role_id) {
-      // We do not synchronize the 'anonymous' or 'authenticated' user role as
-      // they are already taken care of by the 'anonymous' and 'outsider'
-      // internal group roles.
-      if ($role_id == 'anonymous' || $role_id == 'authenticated') {
-        continue;
-      }
-
-      // Build a list of group role definitions but do not save them yet so we
-      // can check whether they already exist in bulk instead of trying to find
-      // out on an individual basis here.
-      foreach (array_keys($group_types) as $group_type_id) {
-        $group_role_id = $this->getGroupRoleId($group_type_id, $role_id);
-        $definitions[$group_role_id] = [
-          'id' => $group_role_id,
-          'label' => $user_roles[$role_id]->label(),
-          'weight' => $user_roles[$role_id]->getWeight(),
-          'internal' => TRUE,
-          'audience' => 'outsider',
-          'group_type' => $group_type_id,
-          'permissions_ui' => FALSE,
-          // Adding our this module and the user role as enforced dependencies
-          // will automatically delete the synchronized group roles when this
-          // module is uninstalled or the user role is deleted.
-          'dependencies' => [
-            'enforced' => [
-              'module' => ['grolesync'],
-              'config' => [$user_roles[$role_id]->getConfigDependencyName()],
-            ],
-          ],
-        ];
-      }
-    }
-
-    // See if the roles we just defined already exist.
-    $existing = $this->entityTypeManager->getStorage('group_role')->loadMultiple(array_keys($definitions));
-
-    // Create the group roles that do not exist yet.
-    foreach (array_diff_key($definitions, $existing) as $definition) {
-      GroupRole::create($definition)->save();
-    }
-  }
-
-  /**
-   * Updates the label of all group roles for a user role.
-   *
-   * @param \Drupal\User\RoleInterface $role
-   *   The user role to update the group role labels for.
-   */
-  public function updateGroupRoleLabels(RoleInterface $role) {
-    /** @var \Drupal\group\Entity\GroupTypeInterface[] $group_types */
-    $group_types = $this->entityTypeManager->getStorage('group_type')->loadMultiple();
-
-    // Return early if there are no group types and, by extension, group roles.
-    if (empty($group_types)) {
-      return;
-    }
-
-    $group_role_ids = [];
-    foreach (array_keys($group_types) as $group_type_id) {
-      $group_role_ids[] = $this->getGroupRoleId($group_type_id, $role->id());
-    }
-
-    /** @var \Drupal\group\Entity\GroupRoleInterface[] $group_roles */
-    $group_roles = $this->entityTypeManager->getStorage('group_role')->loadMultiple($group_role_ids);
-    foreach ($group_roles as $group_role) {
-      $group_role->set('label', $role->label())->save();
-    }
-  }
-
-}
diff --git a/web/modules/group/modules/grolesync/src/GroupRoleSynchronizerInterface.php b/web/modules/group/modules/grolesync/src/GroupRoleSynchronizerInterface.php
deleted file mode 100644
index 7831538bb5..0000000000
--- a/web/modules/group/modules/grolesync/src/GroupRoleSynchronizerInterface.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-namespace Drupal\grolesync;
-
-use Drupal\User\RoleInterface;
-
-/**
- * Synchronizes global site roles to group roles.
- */
-interface GroupRoleSynchronizerInterface {
-
-  /**
-   * Generates an ID for a synchronized group role.
-   *
-   * @param $group_type_id
-   *   The ID of the group type the group role ID should be generated for.
-   * @param $role_id
-   *   The ID of the user role the group role ID should be generated for.
-   *
-   * @return string
-   *   The ID of the group role ID for the given group type and user role.
-   */
-  public function getGroupRoleId($group_type_id, $role_id);
-
-  /**
-   * Creates group roles for all user roles.
-   *
-   * @param string[] $group_type_ids
-   *   (optional) A list of group type IDs to synchronize roles for. Leave empty
-   *   to synchronize roles for all group types.
-   * @param string[] $role_ids
-   *   (optional) A list of user role IDs to synchronize. Leave empty to
-   *   synchronize all user roles.
-   */
-  public function createGroupRoles($group_type_ids = NULL, $role_ids = NULL);
-
-  /**
-   * Updates the label of all group roles for a user role.
-   *
-   * @param \Drupal\User\RoleInterface $role
-   *   The user role to update the group role labels for.
-   */
-  public function updateGroupRoleLabels(RoleInterface $role);
-
-}
diff --git a/web/modules/group/src/Access/GroupAccessResult.php b/web/modules/group/src/Access/GroupAccessResult.php
deleted file mode 100644
index 8f85c7d7f6..0000000000
--- a/web/modules/group/src/Access/GroupAccessResult.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\group\Entity\GroupInterface;
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Extends the AccessResult class with group permission checks.
- */
-abstract class GroupAccessResult extends AccessResult {
-
-  /**
-   * Allows access if the permission is present, neutral otherwise.
-   *
-   * @todo Potentially cache this based on https://www.drupal.org/node/2667018.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group for which to check a permission.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account for which to check a permission.
-   * @param string $permission
-   *   The permission to check for.
-   *
-   * @return \Drupal\Core\Access\AccessResult
-   *   If the account has the permission, isAllowed() will be TRUE, otherwise
-   *   isNeutral() will be TRUE.
-   */
-  public static function allowedIfHasGroupPermission(GroupInterface $group, AccountInterface $account, $permission) {
-    return static::allowedIf($group->hasPermission($permission, $account));
-  }
-
-  /**
-   * Allows access if the permissions are present, neutral otherwise.
-   *
-   * @todo Potentially cache this based on https://www.drupal.org/node/2667018.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group for which to check permissions.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account for which to check permissions.
-   * @param array $permissions
-   *   The permissions to check.
-   * @param string $conjunction
-   *   (optional) 'AND' if all permissions are required, 'OR' in case just one.
-   *   Defaults to 'AND'.
-   *
-   * @return \Drupal\Core\Access\AccessResult
-   *   If the account has the permissions, isAllowed() will be TRUE, otherwise
-   *   isNeutral() will be TRUE.
-   */
-  public static function allowedIfHasGroupPermissions(GroupInterface $group, AccountInterface $account, array $permissions, $conjunction = 'AND') {
-    $access = FALSE;
-
-    if ($conjunction == 'AND' && !empty($permissions)) {
-      $access = TRUE;
-      foreach ($permissions as $permission) {
-        if (!$group->hasPermission($permission, $account)) {
-          $access = FALSE;
-          break;
-        }
-      }
-    }
-    else {
-      foreach ($permissions as $permission) {
-        if ($group->hasPermission($permission, $account)) {
-          $access = TRUE;
-          break;
-        }
-      }
-    }
-
-    return static::allowedIf($access);
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupContentCreateAccessCheck.php b/web/modules/group/src/Access/GroupContentCreateAccessCheck.php
deleted file mode 100644
index 50326ae8e5..0000000000
--- a/web/modules/group/src/Access/GroupContentCreateAccessCheck.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\group\Entity\GroupInterface;
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Session\AccountInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Determines access for group content creation.
- */
-class GroupContentCreateAccessCheck implements AccessInterface {
-
-  /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * Constructs a EntityCreateAccessCheck object.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity manager.
-   */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
-    $this->entityTypeManager = $entity_type_manager;
-  }
-
-  /**
-   * Checks access for group content creation routes.
-   *
-   * All routes using this access check should have a group and plugin_id
-   * parameter and have the _group_content_create_access requirement set to
-   * either 'TRUE' or 'FALSE'.
-   *
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route to check against.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The currently logged in account.
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group in which the content should be created.
-   * @param string $plugin_id
-   *   The group content enabler ID to use for the group content entity.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function access(Route $route, AccountInterface $account, GroupInterface $group, $plugin_id) {
-    $needs_access = $route->getRequirement('_group_content_create_access') === 'TRUE';
-
-    // We can only get the group content type ID if the plugin is installed.
-    if (!$group->getGroupType()->hasContentPlugin($plugin_id)) {
-      return AccessResult::neutral();
-    }
-
-    // Determine whether the user can create group content using the plugin.
-    $group_content_type_id = $group->getGroupType()->getContentPlugin($plugin_id)->getContentTypeConfigId();
-    $access_control_handler = $this->entityTypeManager->getAccessControlHandler('group_content');
-    $access = $access_control_handler->createAccess($group_content_type_id, $account, ['group' => $group]);
-
-    // Only allow access if the user can create group content using the
-    // provided plugin or if he doesn't need access to do so.
-    return AccessResult::allowedIf($access xor !$needs_access);
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupContentCreateAnyAccessCheck.php b/web/modules/group/src/Access/GroupContentCreateAnyAccessCheck.php
deleted file mode 100644
index 3e361b5a7c..0000000000
--- a/web/modules/group/src/Access/GroupContentCreateAnyAccessCheck.php
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Determines access for group content creation.
- */
-class GroupContentCreateAnyAccessCheck implements AccessInterface {
-
-  /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * Constructs a EntityCreateAccessCheck object.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity manager.
-   */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
-    $this->entityTypeManager = $entity_type_manager;
-  }
-
-  /**
-   * Checks access for group content creation routes.
-   *
-   * All routes using this access check should have a group parameter and have
-   * the _group_content_create_any_access requirement set to 'TRUE' or 'FALSE'.
-   *
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route to check against.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The currently logged in account.
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group in which the content should be created.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function access(Route $route, AccountInterface $account, GroupInterface $group) {
-    $needs_access = $route->getRequirement('_group_content_create_any_access') === 'TRUE';
-
-    // Get the group content access control handler.
-    $access_control_handler = $this->entityTypeManager->getAccessControlHandler('group_content');
-
-    // Retrieve all of the group content type IDs for the group.
-    $storage = $this->entityTypeManager->getStorage('group_content_type');
-    $entity_query = $storage->getQuery();
-    $entity_query->condition('group_type', $group->bundle());
-    $group_content_type_ids = $entity_query->execute();
-
-    // Find out which ones the user has access to create.
-    foreach ($group_content_type_ids as $group_content_type_id) {
-      if ($access_control_handler->createAccess($group_content_type_id, $account, ['group' => $group])) {
-        // Allow access if the route flag was set to 'TRUE'.
-        return AccessResult::allowedIf($needs_access);
-      }
-    }
-
-    // If we got this far, it means the user could not create any content in the
-    // group. So only allow access if the route flag was set to 'FALSE'.
-    return AccessResult::allowedIf(!$needs_access);
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupContentCreateAnyEntityAccessCheck.php b/web/modules/group/src/Access/GroupContentCreateAnyEntityAccessCheck.php
deleted file mode 100644
index e31e921d56..0000000000
--- a/web/modules/group/src/Access/GroupContentCreateAnyEntityAccessCheck.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Determines access for group content target entity creation.
- */
-class GroupContentCreateAnyEntityAccessCheck implements AccessInterface {
-
-  /**
-   * Checks access for group content target entity creation routes.
-   *
-   * All routes using this access check should have a group parameter and have
-   * the _group_content_create_any_entity_access requirement set to 'TRUE' or
-   * 'FALSE'.
-   *
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route to check against.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The currently logged in account.
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group in which the content should be created.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function access(Route $route, AccountInterface $account, GroupInterface $group) {
-    $needs_access = $route->getRequirement('_group_content_create_any_entity_access') === 'TRUE';
-
-    // Retrieve all of the group content plugins for the group.
-    $plugins = $group->getGroupType()->getInstalledContentPlugins();
-
-    // Find out which ones allow the user to create a target entity.
-    foreach ($plugins as $plugin) {
-      /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-      if ($plugin->createEntityAccess($group, $account)->isAllowed()) {
-        // Allow access if the route flag was set to 'TRUE'.
-        return AccessResult::allowedIf($needs_access);
-      }
-    }
-
-    // If we got this far, it means the user could not create any content in the
-    // group. So only allow access if the route flag was set to 'FALSE'.
-    return AccessResult::allowedIf(!$needs_access);
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupContentCreateEntityAccessCheck.php b/web/modules/group/src/Access/GroupContentCreateEntityAccessCheck.php
deleted file mode 100644
index f79d1aab63..0000000000
--- a/web/modules/group/src/Access/GroupContentCreateEntityAccessCheck.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\group\Entity\GroupInterface;
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Session\AccountInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Determines access for group content target entity creation.
- */
-class GroupContentCreateEntityAccessCheck implements AccessInterface {
-
-  /**
-   * Checks access for group content target entity creation routes.
-   *
-   * All routes using this access check should have a group and plugin_id
-   * parameter and have the _group_content_create_entity_access requirement set
-   * to either 'TRUE' or 'FALSE'.
-   *
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route to check against.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The currently logged in account.
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group in which the content should be created.
-   * @param string $plugin_id
-   *   The group content enabler ID to use for the group content entity.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function access(Route $route, AccountInterface $account, GroupInterface $group, $plugin_id) {
-    $needs_access = $route->getRequirement('_group_content_create_entity_access') === 'TRUE';
-
-    // We can only get the group content type ID if the plugin is installed.
-    if (!$group->getGroupType()->hasContentPlugin($plugin_id)) {
-      return AccessResult::neutral();
-    }
-
-    // Determine whether the user can create entities of the provided type.
-    $plugin = $group->getGroupType()->getContentPlugin($plugin_id);
-    $access = $plugin->createEntityAccess($group, $account)->isAllowed();
-
-    // Only allow access if the user can create group content target entities
-    // using the provided plugin or if he doesn't need access to do so.
-    return AccessResult::allowedIf($access xor !$needs_access);
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupInstalledContentAccessCheck.php b/web/modules/group/src/Access/GroupInstalledContentAccessCheck.php
deleted file mode 100644
index a4453f8d28..0000000000
--- a/web/modules/group/src/Access/GroupInstalledContentAccessCheck.php
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\group\Entity\GroupInterface;
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Session\AccountInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Determines access to routes based on whether a content plugin is installed.
- */
-class GroupInstalledContentAccessCheck implements AccessInterface {
-
-  /**
-   * Checks access.
-   *
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route to check against.
-   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
-   *   The parametrized route.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account to check access for.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) {
-    $access_string = $route->getRequirement('_group_installed_content');
-
-    // Don't interfere if no plugin ID was specified.
-    if ($access_string === NULL) {
-      return AccessResult::neutral();
-    }
-
-    // Don't interfere if no group was specified.
-    $parameters = $route_match->getParameters();
-    if (!$parameters->has('group')) {
-      return AccessResult::neutral();
-    }
-
-    // Don't interfere if the group isn't a real group.
-    $group = $parameters->get('group');
-    if (!$group instanceof GroupInterface) {
-      return AccessResult::neutral();
-    }
-
-    // We default to not granting access.
-    $access = FALSE;
-
-    // Allow to conjunct the plugin IDs with OR ('+') or AND (',').
-    $plugin_ids = explode(',', $access_string);
-    if (count($plugin_ids) > 1) {
-      $access = TRUE;
-
-      foreach ($plugin_ids as $plugin_id) {
-        if (!$group->getGroupType()->hasContentPlugin($plugin_id)) {
-          $access = FALSE;
-          break;
-        }
-      }
-    }
-    else {
-      $plugin_ids = explode('+', $access_string);
-      foreach ($plugin_ids as $plugin_id) {
-        if ($group->getGroupType()->hasContentPlugin($plugin_id)) {
-          $access = TRUE;
-          break;
-        }
-      }
-    }
-
-    return AccessResult::allowedIf($access);
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupMemberAccessCheck.php b/web/modules/group/src/Access/GroupMemberAccessCheck.php
deleted file mode 100644
index d28a995276..0000000000
--- a/web/modules/group/src/Access/GroupMemberAccessCheck.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\group\Entity\GroupInterface;
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Session\AccountInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Determines access to routes based on whether a user is a member of a group.
- */
-class GroupMemberAccessCheck implements AccessInterface {
-
-  /**
-   * Checks access.
-   *
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route to check against.
-   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
-   *   The parametrized route.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account to check access for.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) {
-    $member_only = $route->getRequirement('_group_member') === 'TRUE';
-
-    // Don't interfere if no group was specified.
-    $parameters = $route_match->getParameters();
-    if (!$parameters->has('group')) {
-      return AccessResult::neutral();
-    }
-
-    // Don't interfere if the group isn't a real group.
-    $group = $parameters->get('group');
-    if (!$group instanceof GroupInterface) {
-      return AccessResult::neutral();
-    }
-
-    // Only allow access if the user is a member of the group and _group_member
-    // is set to TRUE or the other way around.
-    return AccessResult::allowedIf($group->getMember($account) xor !$member_only);
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupOwnsContentAccessCheck.php b/web/modules/group/src/Access/GroupOwnsContentAccessCheck.php
deleted file mode 100644
index b80eb7f837..0000000000
--- a/web/modules/group/src/Access/GroupOwnsContentAccessCheck.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\group\Entity\GroupInterface;
-use Drupal\group\Entity\GroupContentInterface;
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Session\AccountInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Determines access to routes based on whether a piece of group content belongs
- * to the group that was also specified in the route.
- */
-class GroupOwnsContentAccessCheck implements AccessInterface {
-
-  /**
-   * Checks access.
-   *
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route to check against.
-   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
-   *   The parametrized route.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account to check access for.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) {
-    $must_own_content = $route->getRequirement('_group_owns_content') === 'TRUE';
-
-    // Don't interfere if no group or group content was specified.
-    $parameters = $route_match->getParameters();
-    if (!$parameters->has('group') || !$parameters->has('group_content')) {
-      return AccessResult::neutral();
-    }
-
-    // Don't interfere if the group isn't a real group.
-    $group = $parameters->get('group');
-    if (!$group instanceof GroupInterface) {
-      return AccessResult::neutral();
-    }
-
-    // Don't interfere if the group content isn't a real group content entity.
-    $group_content = $parameters->get('group_content');
-    if (!$group_content instanceof GroupContentInterface) {
-      return AccessResult::neutral();
-    }
-
-    // If we have a group and group content, see if the owner matches.
-    $group_owns_content = $group_content->getGroup()->id() == $group->id();
-
-    // Only allow access if the group content is owned by the group and
-    // _group_owns_content is set to TRUE or the other way around.
-    return AccessResult::allowedIf($group_owns_content xor !$must_own_content);
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupPermissionAccessCheck.php b/web/modules/group/src/Access/GroupPermissionAccessCheck.php
deleted file mode 100644
index 709bb23aa3..0000000000
--- a/web/modules/group/src/Access/GroupPermissionAccessCheck.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\group\Entity\GroupInterface;
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Session\AccountInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Determines access to routes based on permissions defined via
- * $module.group_permissions.yml files.
- */
-class GroupPermissionAccessCheck implements AccessInterface {
-
-  /**
-   * Checks access.
-   *
-   * @param \Symfony\Component\Routing\Route $route
-   *   The route to check against.
-   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
-   *   The parametrized route.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account to check access for.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) {
-    $permission = $route->getRequirement('_group_permission');
-
-    // Don't interfere if no permission was specified.
-    if ($permission === NULL) {
-      return AccessResult::neutral();
-    }
-
-    // Don't interfere if no group was specified.
-    $parameters = $route_match->getParameters();
-    if (!$parameters->has('group')) {
-      return AccessResult::neutral();
-    }
-
-    // Don't interfere if the group isn't a real group.
-    $group = $parameters->get('group');
-    if (!$group instanceof GroupInterface) {
-      return AccessResult::neutral();
-    }
-
-    // Allow to conjunct the permissions with OR ('+') or AND (',').
-    $split = explode(',', $permission);
-    if (count($split) > 1) {
-      return GroupAccessResult::allowedIfHasGroupPermissions($group, $account, $split, 'AND');
-    }
-    else {
-      $split = explode('+', $permission);
-      return GroupAccessResult::allowedIfHasGroupPermissions($group, $account, $split, 'OR');
-    }
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupPermissionHandler.php b/web/modules/group/src/Access/GroupPermissionHandler.php
deleted file mode 100644
index 2726c7d0e4..0000000000
--- a/web/modules/group/src/Access/GroupPermissionHandler.php
+++ /dev/null
@@ -1,296 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\Component\Discovery\YamlDiscovery;
-use Drupal\Component\Render\MarkupInterface;
-use Drupal\Core\Controller\ControllerResolverInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\Core\StringTranslation\TranslationInterface;
-use Drupal\group\Entity\GroupTypeInterface;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-
-/**
- * Provides the available permissions based on yml files.
- *
- * To define permissions you can use a $module.group.permissions.yml file. This
- * file defines machine names and human-readable names for each permission. The
- * machine names are the canonical way to refer to permissions for access
- * checking. Each permission may also have a restrict access and/or warning
- * message, keys defining what roles it applies to and a description.
- *
- * If your module needs to define dynamic permissions you can use the
- * permission_callbacks key to declare a callable that will return an array of
- * permissions, keyed by machine name. Each item in the array can contain the
- * same keys as an entry in $module.group.permissions.yml.
- *
- * To find a list of supported permission keys, have a look at the documentation
- * of GroupPermissionHandlerInterface::getPermissions().
- *
- * Here is an example from the group module itself (comments have been added):
- * @code
- * # The key is the permission machine name, and is required.
- * edit group:
- *   # (required) Human readable name of the permission used in the UI.
- *   title: 'Edit group'
- *   description: 'Edit the group information'
- *
- * # An array of callables used to generate dynamic permissions.
- * permission_callbacks:
- *   # Each item in the array should return an associative array with one or
- *   # more permissions following the same keys as the permission defined above.
- *   - Drupal\my_module\MyModuleGroupPermissions::permissions
- * @endcode
- *
- * @see group.group.permissions.yml
- * @see \Drupal\group\Access\GroupPermissionHandlerInterface::getPermissions()
- */
-class GroupPermissionHandler implements GroupPermissionHandlerInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The module handler.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
-   * The YAML discovery class to find all .group.permissions.yml files.
-   *
-   * @var \Drupal\Component\Discovery\YamlDiscovery
-   */
-  protected $yamlDiscovery;
-
-  /**
-   * The controller resolver.
-   *
-   * @var \Drupal\Core\Controller\ControllerResolverInterface
-   */
-  protected $controllerResolver;
-
-  /**
-   * The group content enabler plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * Constructs a new PermissionHandler.
-   *
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
-   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
-   *   The string translation.
-   * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
-   *   The controller resolver.
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content enabler plugin manager.
-   */
-  public function __construct(ModuleHandlerInterface $module_handler, TranslationInterface $string_translation, ControllerResolverInterface $controller_resolver, GroupContentEnablerManagerInterface $plugin_manager) {
-    $this->moduleHandler = $module_handler;
-    $this->stringTranslation = $string_translation;
-    $this->controllerResolver = $controller_resolver;
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * Gets the YAML discovery.
-   *
-   * @return \Drupal\Component\Discovery\YamlDiscovery
-   *   The YAML discovery.
-   */
-  protected function getYamlDiscovery() {
-    if (!isset($this->yamlDiscovery)) {
-      $this->yamlDiscovery = new YamlDiscovery('group.permissions', $this->moduleHandler->getModuleDirectories());
-    }
-    return $this->yamlDiscovery;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPermissions($include_plugins = FALSE) {
-    $all_permissions = $this->buildPermissionsYaml();
-
-    // Add the plugin defined permissions to the whole. We query all defined
-    // plugins to avoid scenarios where modules want to ship with default
-    // configuration but can't because their plugins may not be installed along
-    // with the module itself (i.e.: non-enforced plugins).
-    if ($include_plugins) {
-      foreach ($this->pluginManager->getAll() as $plugin) {
-        /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-        foreach ($plugin->getPermissions() as $permission_name => $permission) {
-          $permission += ['provider' => $plugin->getProvider()];
-          $all_permissions[$permission_name] = $this->completePermission($permission);
-        }
-      }
-    }
-
-    return $this->sortPermissions($all_permissions);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPermissionsByGroupType(GroupTypeInterface $group_type) {
-    $all_permissions = $this->buildPermissionsYaml();
-
-    // Add the plugin defined permissions to the whole.
-    foreach ($group_type->getInstalledContentPlugins() as $plugin) {
-      /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-      foreach ($plugin->getPermissions() as $permission_name => $permission) {
-        $permission += ['provider' => $plugin->getProvider()];
-        $all_permissions[$permission_name] = $this->completePermission($permission);
-      }
-    }
-
-    return $this->sortPermissions($all_permissions);
-  }
-
-  /**
-   * Completes a permission by adding in defaults and translating its strings.
-   *
-   * @param array $permission
-   *   The raw permission to complete.
-   *
-   * @return array
-   *   A permission which is guaranteed to have all the required keys set.
-   */
-  protected function completePermission($permission) {
-    $permission += [
-      'title_args' => [],
-      'description' => '',
-      'description_args' => [],
-      'restrict access' => FALSE,
-      'warning' => !empty($permission['restrict access']) ? 'Warning: Give to trusted roles only; this permission has security implications.' : '',
-      'warning_args' => [],
-      'allowed for' => ['anonymous', 'outsider', 'member'],
-    ];
-
-    // Translate the title and optionally the description and warning.
-    $permission['title'] = $this->t($permission['title'], $permission['title_args']);
-    if (!empty($permission['description'])) {
-      $permission['description'] = $this->t($permission['description'], $permission['description_args']);
-    }
-    if (!empty($permission['warning'])) {
-      $permission['warning'] = $this->t($permission['warning'], $permission['warning_args']);
-    }
-
-    return $permission;
-  }
-
-  /**
-   * Builds all permissions provided by .group.permissions.yml files.
-   *
-   * @return array[]
-   *   An array of permissions as described in ::getPermissions().
-   *
-   * @see \Drupal\group\Access\PermissionHandlerInterface::getPermissions()
-   */
-  protected function buildPermissionsYaml() {
-    $all_permissions = [];
-    $all_callback_permissions = [];
-
-    foreach ($this->getYamlDiscovery()->findAll() as $provider => $permissions) {
-      // The top-level 'permissions_callback' is a list of methods in controller
-      // syntax, see \Drupal\Core\Controller\ControllerResolver. These methods
-      // should return an array of permissions in the same structure.
-      if (isset($permissions['permission_callbacks'])) {
-        foreach ($permissions['permission_callbacks'] as $permission_callback) {
-          $callback = $this->controllerResolver->getControllerFromDefinition($permission_callback);
-          if ($callback_permissions = call_user_func($callback)) {
-            // Add any callback permissions to the array of permissions. In case
-            // of any conflict, the YAML ones will take precedence.
-            foreach ($callback_permissions as $name => $callback_permission) {
-              if (!is_array($callback_permission)) {
-                $callback_permission = ['title' => $callback_permission];
-              }
-
-              // Set the provider if none was specified.
-              $callback_permission += ['provider' => $provider];
-
-              $all_callback_permissions[$name] = $callback_permission;
-            }
-          }
-        }
-
-        unset($permissions['permission_callbacks']);
-      }
-
-      foreach ($permissions as $permission_name => $permission) {
-        if (!is_array($permission)) {
-          $permission = ['title' => $permission];
-        }
-
-        // Set the provider if none was spec
-        $permissions[$permission_name] = $permission + ['provider' => $provider];
-      }
-
-      $all_permissions += $permissions;
-    }
-
-    // Combine all defined permissions and set the rest of the defaults.
-    $full_permissions = $all_permissions + $all_callback_permissions;
-    foreach ($full_permissions as $permission_name => $permission) {
-      $full_permissions[$permission_name] = $this->completePermission($permission);
-    }
-
-    return $full_permissions;
-  }
-
-  /**
-   * Sorts the given permissions by provider name first and then by title.
-   *
-   * @param array $permissions
-   *   The permissions to be sorted.
-   *
-   * @return array[]
-   *   An array of permissions as described in ::getPermissions().
-   *
-   * @see \Drupal\group\Access\PermissionHandlerInterface::getPermissions()
-   */
-  protected function sortPermissions(array $permissions = []) {
-    $modules = $this->getModuleNames();
-
-    // Sort all permissions by provider name first and then by title.
-    uasort($permissions, function (array $permission_a, array $permission_b) use ($modules) {
-      if ($modules[$permission_a['provider']] == $modules[$permission_b['provider']]) {
-        // Account for the possibility that titles may already be instances of
-        // \Drupal\Core\StringTranslation\TranslatableMarkup.
-        $title_a = $permission_a['title'] instanceof MarkupInterface
-          ? $permission_a['title']->__toString()
-          : $permission_a['title'];
-        $title_b = $permission_b['title'] instanceof MarkupInterface
-          ? $permission_b['title']->__toString()
-          : $permission_b['title'];
-
-        return strip_tags($title_a) > strip_tags($title_b);
-      }
-      else {
-        return $modules[$permission_a['provider']] > $modules[$permission_b['provider']];
-      }
-    });
-
-    return $permissions;
-  }
-
-  /**
-   * Returns all module names.
-   *
-   * @return string[]
-   *   Returns the human readable names of all modules keyed by machine name.
-   */
-  protected function getModuleNames() {
-    $modules = [];
-    foreach (array_keys($this->moduleHandler->getModuleList()) as $module) {
-      $modules[$module] = $this->moduleHandler->getName($module);
-    }
-    asort($modules);
-    return $modules;
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupPermissionHandlerInterface.php b/web/modules/group/src/Access/GroupPermissionHandlerInterface.php
deleted file mode 100644
index cec5272b02..0000000000
--- a/web/modules/group/src/Access/GroupPermissionHandlerInterface.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\group\Entity\GroupTypeInterface;
-
-/**
- * Defines an interface to list available permissions.
- */
-interface GroupPermissionHandlerInterface {
-
-  /**
-   * Gets all defined group permissions.
-   * 
-   * @param bool $include_plugins
-   *   (optional) Whether to also include the permissions defined by all
-   *   installed group content plugins. Defaults to FALSE.
-   *
-   * @return array
-   *   An array whose keys are permission names and whose corresponding values
-   *   are arrays containing the following key-value pairs:
-   *   - title: The untranslated human-readable name of the permission, to be
-   *     shown on the permission administration page. You may use placeholders
-   *     as you would in t().
-   *   - title_args: (optional) The placeholder values for the title.
-   *   - description: (optional) An untranslated description of what the
-   *     permission does. You may use placeholders as you would in t().
-   *   - description_args: (optional) The placeholder values for the description.
-   *   - restrict access: (optional) A boolean which can be set to TRUE to
-   *     indicate that site administrators should restrict access to this
-   *     permission to trusted users. This should be used for permissions that
-   *     have inherent security risks across a variety of potential use cases.
-   *     When set to TRUE, a standard warning message will be displayed with the
-   *     permission on the permission administration page. Defaults to FALSE.
-   *   - warning: (optional) An untranslated warning message to display for this
-   *     permission on the permission administration page. This warning
-   *     overrides the automatic warning generated by 'restrict access' being
-   *     set to TRUE. This should rarely be used, since it is important for all
-   *     permissions to have a clear, consistent security warning that is the
-   *     same across the site. Use the 'description' key instead to provide any
-   *     information that is specific to the permission you are defining. You
-   *     may use placeholders as you would in t().
-   *   - warning_args: (optional) The placeholder values for the warning.
-   *   - allowed for: (optional) An array of strings that define which
-   *     membership types can use this permission. Possible values are:
-   *     'anonymous', 'outsider', 'member'. Will default to all three when left
-   *     empty.
-   *   - provider: (optional) The provider name of the permission. Defaults to
-   *     the module providing the permission. You may set this to another
-   *     module's name to make it appear as if the permission was provided by
-   *     that module.
-   */
-  public function getPermissions($include_plugins = FALSE);
-
-  /**
-   * Gets all defined group permissions for a group type.
-   *
-   * Unlike ::getPermissions(), this also includes the group permissions that
-   * were defined by the plugins installed on the group type.
-   *
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   The group type to retrieve the permission list for.
-   *
-   * @return array
-   *   The full permission list, structured like ::getPermissions().
-   * 
-   * @see \Drupal\group\Access\GroupPermissionHandlerInterface::getPermissions()
-   */
-  public function getPermissionsByGroupType(GroupTypeInterface $group_type);
-
-}
diff --git a/web/modules/group/src/Access/GroupPermissions.php b/web/modules/group/src/Access/GroupPermissions.php
deleted file mode 100644
index 5a0941f47b..0000000000
--- a/web/modules/group/src/Access/GroupPermissions.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\Core\Routing\UrlGeneratorTrait;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\group\Entity\GroupType;
-
-/**
- * Provides dynamic permissions for groups of different types.
- */
-class GroupPermissions {
-
-  use StringTranslationTrait;
-  use UrlGeneratorTrait;
-
-  /**
-   * Returns an array of group type permissions.
-   *
-   * @return array
-   *   The group type permissions.
-   *   @see \Drupal\user\PermissionHandlerInterface::getPermissions()
-   */
-  public function groupTypePermissions() {
-    $perms = [];
-    
-    // Generate group permissions for all group types.
-    foreach (GroupType::loadMultiple() as $type) {
-      $perms += $this->buildPermissions($type);
-    }
-
-    return $perms;
-  }
-
-  /**
-   * Returns a list of group permissions for a given group type.
-   *
-   * @param \Drupal\group\Entity\GroupType $type
-   *   The group type.
-   *
-   * @return array
-   *   An associative array of permission names and descriptions.
-   */
-  protected function buildPermissions(GroupType $type) {
-    $type_id = $type->id();
-    $type_params = ['%type_name' => $type->label()];
-
-    return [
-      "create $type_id group" => [
-        'title' => $this->t('%type_name: Create new group', $type_params),
-      ],
-    ];
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupPermissionsHashGenerator.php b/web/modules/group/src/Access/GroupPermissionsHashGenerator.php
deleted file mode 100644
index b30ad6eaa8..0000000000
--- a/web/modules/group/src/Access/GroupPermissionsHashGenerator.php
+++ /dev/null
@@ -1,150 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\PrivateKey;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\Site\Settings;
-use Drupal\group\Entity\GroupInterface;
-
-/**
- * Generates and caches the permissions hash for a group membership.
- */
-class GroupPermissionsHashGenerator implements GroupPermissionsHashGeneratorInterface {
-
-  /**
-   * The private key service.
-   *
-   * @var \Drupal\Core\PrivateKey
-   */
-  protected $privateKey;
-
-  /**
-   * The cache backend interface to use for the persistent cache.
-   *
-   * @var \Drupal\Core\Cache\CacheBackendInterface
-   */
-  protected $cache;
-
-  /**
-   * The cache backend interface to use for the static cache.
-   *
-   * @var \Drupal\Core\Cache\CacheBackendInterface
-   */
-  protected $static;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * Constructs a GroupPermissionsHashGenerator object.
-   *
-   * @param \Drupal\Core\PrivateKey $private_key
-   *   The private key service.
-   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
-   *   The cache backend interface to use for the persistent cache.
-   * @param \Drupal\Core\Cache\CacheBackendInterface
-   *   The cache backend interface to use for the static cache.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   */
-  public function __construct(PrivateKey $private_key, CacheBackendInterface $cache, CacheBackendInterface $static, EntityTypeManagerInterface $entity_type_manager) {
-    $this->privateKey = $private_key;
-    $this->cache = $cache;
-    $this->static = $static;
-    $this->entityTypeManager = $entity_type_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * Cached by role, invalidated whenever permissions change.
-   */
-  public function generate(GroupInterface $group, AccountInterface $account) {
-    // If the user can bypass group access we return a unique hash.
-    if ($account->hasPermission('bypass group access')) {
-      return $this->hash('bypass-group-access');
-    }
-
-    // Retrieve all of the group roles the user may get for the group.
-    $group_roles = $this->groupRoleStorage()->loadByUserAndGroup($account, $group);
-
-    // Sort the group roles by ID.
-    ksort($group_roles);
-
-    // Create a cache ID based on the role IDs.
-    $role_list = implode(',', array_keys($group_roles));
-    $cid = "group_permissions_hash:$role_list";
-
-    // Retrieve the hash from the static cache if available.
-    if ($static_cache = $this->static->get($cid)) {
-      return $static_cache->data;
-    }
-    else {
-      // Build cache tags for the individual group roles.
-      $tags = Cache::buildTags('config:group.role', array_keys($group_roles), '.');
-
-      // Retrieve the hash from the persistent cache if available.
-      if ($cache = $this->cache->get($cid)) {
-        $permissions_hash = $cache->data;
-      }
-      // Otherwise generate the hash and store it in the persistent cache.
-      else {
-        $permissions_hash = $this->doGenerate($group_roles);
-        $this->cache->set($cid, $permissions_hash, Cache::PERMANENT, $tags);
-      }
-
-      // Store the hash in the static cache.
-      $this->static->set($cid, $permissions_hash, Cache::PERMANENT, $tags);
-    }
-
-    return $permissions_hash;
-  }
-
-  /**
-   * Generates a hash that uniquely identifies the group member's permissions.
-   *
-   * @param \Drupal\group\Entity\GroupRoleInterface[] $group_roles
-   *   The group roles to generate the permission hash for.
-   *
-   * @return string
-   *   The permissions hash.
-   */
-  protected function doGenerate(array $group_roles) {
-    $permissions = [];
-    foreach ($group_roles as $group_role) {
-      $permissions = array_merge($permissions, $group_role->getPermissions());
-    }
-    return $this->hash(serialize(array_unique($permissions)));
-  }
-
-  /**
-   * Hashes the given string.
-   *
-   * @param string $identifier
-   *   The string to be hashed.
-   *
-   * @return string
-   *   The hash.
-   */
-  protected function hash($identifier) {
-    return hash('sha256', $this->privateKey->get() . Settings::getHashSalt() . $identifier);
-  }
-
-  /**
-   * Gets the group role storage.
-   *
-   * @return \Drupal\group\Entity\Storage\GroupRoleStorageInterface
-   */
-  protected function groupRoleStorage() {
-    return $this->entityTypeManager->getStorage('group_role');
-  }
-
-}
diff --git a/web/modules/group/src/Access/GroupPermissionsHashGeneratorInterface.php b/web/modules/group/src/Access/GroupPermissionsHashGeneratorInterface.php
deleted file mode 100644
index aafdc25347..0000000000
--- a/web/modules/group/src/Access/GroupPermissionsHashGeneratorInterface.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-namespace Drupal\group\Access;
-
-use Drupal\group\Entity\GroupInterface;
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Defines the group permissions hash generator interface.
- */
-interface GroupPermissionsHashGeneratorInterface {
-
-  /**
-   * Generates a hash that uniquely identifies a group member's permissions.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group for which to get the permissions hash.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The user account for which to get the permissions hash.
-   *
-   * @return string
-   *   A permissions hash.
-   */
-  public function generate(GroupInterface $group, AccountInterface $account);
-
-}
diff --git a/web/modules/group/src/Annotation/GroupContentEnabler.php b/web/modules/group/src/Annotation/GroupContentEnabler.php
deleted file mode 100644
index 01545d9e88..0000000000
--- a/web/modules/group/src/Annotation/GroupContentEnabler.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-
-namespace Drupal\group\Annotation;
-
-use Drupal\Component\Annotation\Plugin;
-
-/**
- * Defines a GroupContentEnabler annotation object.
- *
- * Plugin Namespace: Plugin\GroupContentEnabler
- *
- * For a working example, see
- * \Drupal\group\Plugin\GroupContentEnabler\GroupMembership
- *
- * @see \Drupal\group\Plugin\GroupContentEnablerInterface
- * @see \Drupal\group\Plugin\GroupContentEnablerManager
- * @see plugin_api
- *
- * @Annotation
- */
-class GroupContentEnabler extends Plugin {
-
-  /**
-   * The plugin ID.
-   *
-   * @var string
-   */
-  public $id;
-
-  /**
-   * The human-readable name of the GroupContentEnabler plugin.
-   *
-   * @var \Drupal\Core\Annotation\Translation
-   *
-   * @ingroup plugin_translatable
-   */
-  public $label;
-
-  /**
-   * A short description of the GroupContentEnabler plugin.
-   *
-   * @var \Drupal\Core\Annotation\Translation
-   *
-   * @ingroup plugin_translatable
-   */
-  public $description;
-
-  /**
-   * The ID of the entity type you want to enable as group content.
-   *
-   * @var string
-   */
-  public $entity_type_id;
-
-  /**
-   * (optional) The bundle of the entity type you want to enable as group content.
-   *
-   * Do not specify if your plugin manages all bundles.
-   *
-   * @var string|false
-   */
-  public $entity_bundle = FALSE;
-
-  /**
-   * (optional) Whether the plugin defines entity access.
-   *
-   * This controls whether you can create entities within the group (TRUE) or
-   * only add existing ones (FALSE). It also generates the necessary group
-   * permissions when enabled.
-   *
-   * Eventually, this will even generate entity access records for you, but that
-   * will only happen after the patch in https://www.drupal.org/node/777578 has
-   * been committed to Drupal core.
-   *
-   * @var bool
-   */
-  public $entity_access = FALSE;
-
-  /**
-   * (optional) The key to use in automatically generated paths.
-   *
-   * Will be added to the entity tokens so modules like Pathauto may use it.
-   *
-   * @var string
-   */
-  public $pretty_path_key;
-
-  /**
-   * (optional) The label for the entity reference field.
-   *
-   * @var string
-   */
-  public $reference_label;
-
-  /**
-   * (optional) The description for the entity reference field.
-   *
-   * @var string
-   */
-  public $reference_description;
-
-  /**
-   * (optional) Whether this plugin is always on.
-   *
-   * @var bool
-   */
-  public $enforced = FALSE;
-
-}
diff --git a/web/modules/group/src/Breadcrumb/GroupContentTypeBreadcrumbBuilder.php b/web/modules/group/src/Breadcrumb/GroupContentTypeBreadcrumbBuilder.php
deleted file mode 100644
index 4f4cc73ae5..0000000000
--- a/web/modules/group/src/Breadcrumb/GroupContentTypeBreadcrumbBuilder.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-namespace Drupal\group\Breadcrumb;
-
-use Drupal\group\Entity\GroupContentTypeInterface;
-use Drupal\Core\Link;
-use Drupal\Core\Breadcrumb\Breadcrumb;
-use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-
-/**
- * Provides a custom breadcrumb builder for group content type paths.
- */
-class GroupContentTypeBreadcrumbBuilder implements BreadcrumbBuilderInterface {
-  use StringTranslationTrait;
-
-  /**
-   * @inheritdoc
-   */
-  public function applies(RouteMatchInterface $route_match) {
-    // Only apply to paths containing a group content type.
-    if ($route_match->getParameter('group_content_type') instanceof GroupContentTypeInterface) {
-      return TRUE;
-    }
-  }
-
-  /**
-   * @inheritdoc
-   */
-  public function build(RouteMatchInterface $route_match) {
-    /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-    $group_content_type = $route_match->getParameter('group_content_type');
-    $group_type = $group_content_type->getGroupType();
-
-    $breadcrumb = new Breadcrumb();
-    $breadcrumb->addLink(Link::createFromRoute($this->t('Home'), '<front>'));
-    $breadcrumb->addLink(Link::createFromRoute($this->t('Administration'), 'system.admin'));
-    $breadcrumb->addLink(Link::createFromRoute($this->t('Groups'), 'entity.group.collection'));
-    $breadcrumb->addLink(Link::createFromRoute($this->t('Group types'), 'entity.group_type.collection'));
-    $breadcrumb->addLink(Link::createFromRoute($group_type->label(), 'entity.group_type.edit_form', ['group_type' => $group_type->id()]));
-    $breadcrumb->addLink(Link::createFromRoute($this->t('Content'), 'entity.group_type.content_plugins', ['group_type' => $group_type->id()]));
-
-    // Add a link to the Configure page for any non-default tab.
-    if ($route_match->getRouteName() != 'entity.group_content_type.edit_form') {
-      $breadcrumb->addLink(Link::createFromRoute($this->t('Configure'), 'entity.group_content_type.edit_form', ['group_content_type' => $group_content_type->id()]));
-    }
-
-    // Breadcrumb needs to have the group type and group content type as
-    // cacheable dependencies because any changes to them should be reflected.
-    $breadcrumb->addCacheableDependency($group_type);
-    $breadcrumb->addCacheableDependency($group_content_type);
-
-    // This breadcrumb builder is based on a route parameter, and hence it
-    // depends on the 'route' cache context.
-    $breadcrumb->addCacheContexts(['route']);
-
-    return $breadcrumb;
-  }
-
-}
diff --git a/web/modules/group/src/Cache/Context/GroupCacheContext.php b/web/modules/group/src/Cache/Context/GroupCacheContext.php
deleted file mode 100644
index 718114a8bf..0000000000
--- a/web/modules/group/src/Cache/Context/GroupCacheContext.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-namespace Drupal\group\Cache\Context;
-
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\Cache\Context\CacheContextInterface;
-
-/**
- * Defines a cache context for "per group" caching.
- * 
- * Please note: This cache context uses the group from the current route as the
- * value object to work with. This context is therefore only to be used with
- * data that was based on the group from the route. You can retrieve it using
- * the 'entity:group' context provided by the 'group.group_route_context'
- * service. See an example at: \Drupal\group\Plugin\Block\GroupOperationsBlock.
- *
- * Cache context ID: 'group'.
- */
-class GroupCacheContext extends GroupCacheContextBase implements CacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Group');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    // If we have an existing group, we can simply return its ID because that is
-    // a unique identifier. However, when dealing with unsaved groups, they all
-    // share the same ID 0. In order to avoid collisions when the 'group.type'
-    // context gets optimized away, we need to make the unsaved groups unique
-    // per type as well.
-    return $this->hasExistingGroup()
-      ? $this->group->id()
-      : $this->group->bundle() . '-0';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheableMetadata() {
-    // You can't update a group's ID. So even if somehow this top-level cache
-    // context got optimized away, it does not need to set a cache tag for a
-    // group entity as the ID is not invalidated by a save.
-    return new CacheableMetadata();
-  }
-
-}
diff --git a/web/modules/group/src/Cache/Context/GroupCacheContextBase.php b/web/modules/group/src/Cache/Context/GroupCacheContextBase.php
deleted file mode 100644
index b9865fbc5b..0000000000
--- a/web/modules/group/src/Cache/Context/GroupCacheContextBase.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-
-namespace Drupal\group\Cache\Context;
-
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\group\Context\GroupRouteContextTrait;
-
-/**
- * Base class for group-based cache contexts.
- *
- * This cache context retrieves the group from the active route by re-using the
- * logic in the injected context provider service, which defaults to
- * \Drupal\group\Context\GroupRouteContext.
- *
- * Subclasses need to implement either
- * \Drupal\Core\Cache\Context\CacheContextInterface or
- * \Drupal\Core\Cache\Context\CalculatedCacheContextInterface.
- */
-abstract class GroupCacheContextBase {
-
-  /**
-   * Instead of relying on the Group context provider, we re-use some of its
-   * logic for retrieving a group entity from the route. This is because cache
-   * contexts need to be really fast and loading the whole context service is
-   * slower than simply using the 'current_route_match' service.
-   */
-  use GroupRouteContextTrait;
-
-  /**
-   * The group entity.
-   *
-   * @var \Drupal\group\Entity\GroupInterface
-   */
-  protected $group;
-
-  /**
-   * Constructs a new GroupCacheContextBase class.
-   *
-   * @param \Drupal\Core\Routing\RouteMatchInterface $current_route_match
-   *   The current route match object.
-   */
-  public function __construct(RouteMatchInterface $current_route_match) {
-    $this->currentRouteMatch = $current_route_match;
-    $this->group = $this->getGroupFromRoute();
-  }
-
-  /**
-   * Checks whether this context got an existing group from the route.
-   *
-   * @return bool
-   *   Whether we've got an existing group.
-   */
-  protected function hasExistingGroup() {
-    return !empty($this->group) && $this->group->id();
-  }
-
-}
diff --git a/web/modules/group/src/Cache/Context/GroupMembershipAudienceCacheContext.php b/web/modules/group/src/Cache/Context/GroupMembershipAudienceCacheContext.php
deleted file mode 100644
index 8c15bd02b3..0000000000
--- a/web/modules/group/src/Cache/Context/GroupMembershipAudienceCacheContext.php
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-
-namespace Drupal\group\Cache\Context;
-
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\Cache\Context\CacheContextInterface;
-
-/**
- * Defines a cache context for "per group audience" caching.
- *
- * The idea behind this cache context is to allow a piece of content to vary by
- * the fact that a user is a member, outsider or anonymous user with regard to
- * the group.
- *
- * Please note: This cache context uses the group from the current route as the
- * value object to work with. This context is therefore only to be used with
- * data that was based on the group from the route. You can retrieve it using
- * the 'entity:group' context provided by the 'group.group_route_context'
- * service. See an example at: \Drupal\group\Plugin\Block\GroupOperationsBlock.
- *
- * Cache context ID: 'group_membership.audience'.
- */
-class GroupMembershipAudienceCacheContext extends GroupMembershipCacheContextBase implements CacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Group membership audience');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    // If there was no existing group on the route, there can be no membership.
-    if (!$this->hasExistingGroup()) {
-      return 'none';
-    }
-
-    // If there is a membership, we return 'member.
-    if ($this->group->getMember($this->user)) {
-      return 'member';
-    }
-
-    // Otherwise, return 'outsider' or 'anonymous' depending on the user.
-    return $this->user->id() == 0 ? 'anonymous' : 'outsider';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheableMetadata() {
-    // There is nothing that could affect this cache context should it be
-    // optimized away, so return an empty cacheable metadata object.
-    return new CacheableMetadata();
-  }
-
-}
diff --git a/web/modules/group/src/Cache/Context/GroupMembershipCacheContext.php b/web/modules/group/src/Cache/Context/GroupMembershipCacheContext.php
deleted file mode 100644
index 8afc97ae22..0000000000
--- a/web/modules/group/src/Cache/Context/GroupMembershipCacheContext.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-namespace Drupal\group\Cache\Context;
-
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\Cache\Context\CacheContextInterface;
-
-/**
- * Defines a cache context for "per group membership" caching.
- *
- * Please note: This cache context uses the group from the current route as the
- * value object to work with. This context is therefore only to be used with
- * data that was based on the group from the route. You can retrieve it using
- * the 'entity:group' context provided by the 'group.group_route_context'
- * service. See an example at: \Drupal\group\Plugin\Block\GroupOperationsBlock.
- *
- * Cache context ID: 'group_membership'.
- */
-class GroupMembershipCacheContext extends GroupMembershipCacheContextBase implements CacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Group membership');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    // If there was no existing group on the route, there can be no membership.
-    if (!$this->hasExistingGroup()) {
-      return 'none';
-    }
-
-    // If there is a membership, we return the membership ID.
-    if ($group_membership = $this->group->getMember($this->user)) {
-      return $group_membership->getGroupContent()->id();
-    }
-
-    // Otherwise, return the ID of the 'outsider' or 'anonymous' group role,
-    // depending on the user. This is necessary to have a unique identifier to
-    // distinguish between 'outsider' or 'anonymous' users for different group
-    // types.
-    return $this->user->isAnonymous()
-      ? $this->group->getGroupType()->getAnonymousRoleId()
-      : $this->group->getGroupType()->getOutsiderRoleId();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheableMetadata() {
-    // You can't update a group content's ID. So even if somehow this top-level
-    // cache context got optimized away, it does not need to set a cache tag for
-    // a group content entity as the ID is not invalidated by a save.
-    return new CacheableMetadata();
-  }
-
-}
diff --git a/web/modules/group/src/Cache/Context/GroupMembershipCacheContextBase.php b/web/modules/group/src/Cache/Context/GroupMembershipCacheContextBase.php
deleted file mode 100644
index a115c8fbb8..0000000000
--- a/web/modules/group/src/Cache/Context/GroupMembershipCacheContextBase.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-
-namespace Drupal\group\Cache\Context;
-
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Context\GroupRouteContextTrait;
-
-/**
- * Base class for group membership-based cache contexts.
- *
- * This cache context retrieves the group from the active route by re-using the
- * logic in the injected context provider service, which defaults to
- * \Drupal\group\Context\GroupRouteContext.
- *
- * Subclasses need to implement either
- * \Drupal\Core\Cache\Context\CacheContextInterface or
- * \Drupal\Core\Cache\Context\CalculatedCacheContextInterface.
- */
-abstract class GroupMembershipCacheContextBase {
-
-  /**
-   * Instead of relying on the Group context provider, we re-use some of its
-   * logic for retrieving a group entity from the route. This is because cache
-   * contexts need to be really fast and loading the whole context service is
-   * slower than simply using the 'current_route_match' service.
-   */
-  use GroupRouteContextTrait;
-
-  /**
-   * The group entity.
-   *
-   * @var \Drupal\group\Entity\GroupInterface
-   */
-  protected $group;
-
-  /**
-   * The account object.
-   *
-   * @var \Drupal\Core\Session\AccountInterface
-   */
-  protected $user;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * Constructs a new GroupMembershipCacheContextBase class.
-   *
-   * @param \Drupal\Core\Routing\RouteMatchInterface $current_route_match
-   *   The current route match object.
-   * @param \Drupal\Core\Session\AccountInterface $user
-   *   The current user.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   */
-  public function __construct(RouteMatchInterface $current_route_match, AccountInterface $user, EntityTypeManagerInterface $entity_type_manager) {
-    $this->currentRouteMatch = $current_route_match;
-    $this->group = $this->getGroupFromRoute();
-    $this->user = $user;
-    $this->entityTypeManager = $entity_type_manager;
-  }
-
-  /**
-   * Checks whether this context got an existing group from the route.
-   *
-   * @return bool
-   *   Whether we've got an existing group.
-   */
-  protected function hasExistingGroup() {
-    return !empty($this->group) && $this->group->id();
-  }
-
-  /**
-   * Gets the group role storage.
-   *
-   * @return \Drupal\group\Entity\Storage\GroupRoleStorageInterface
-   */
-  protected function groupRoleStorage() {
-    return $this->entityTypeManager->getStorage('group_role');
-  }
-
-}
diff --git a/web/modules/group/src/Cache/Context/GroupMembershipPermissionsCacheContext.php b/web/modules/group/src/Cache/Context/GroupMembershipPermissionsCacheContext.php
deleted file mode 100644
index b51a2dbc59..0000000000
--- a/web/modules/group/src/Cache/Context/GroupMembershipPermissionsCacheContext.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-
-namespace Drupal\group\Cache\Context;
-
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\Cache\Context\CacheContextInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Access\GroupPermissionsHashGeneratorInterface;
-
-/**
- * Defines a cache context for "per group membership permissions" caching.
- *
- * Please note: This cache context uses the group from the current route as the
- * value object to work with. This context is therefore only to be used with
- * data that was based on the group from the route. You can retrieve it using
- * the 'entity:group' context provided by the 'group.group_route_context'
- * service. See an example at: \Drupal\group\Plugin\Block\GroupOperationsBlock.
- *
- * Cache context ID: 'group_membership.roles.permissions'.
- */
-class GroupMembershipPermissionsCacheContext extends GroupMembershipCacheContextBase implements CacheContextInterface {
-
-  /**
-   * The permissions hash generator.
-   *
-   * @var \Drupal\group\Access\GroupPermissionsHashGeneratorInterface
-   */
-  protected $permissionsHashGenerator;
-
-  /**
-   * Constructs a new GroupMembershipPermissionsCacheContext class.
-   *
-   * @param \Drupal\Core\Routing\RouteMatchInterface $current_route_match
-   *   The current route match object.
-   * @param \Drupal\Core\Session\AccountInterface $user
-   *   The current user.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\group\Access\GroupPermissionsHashGeneratorInterface $hash_generator
-   *   The permissions hash generator.
-   */
-  public function __construct(RouteMatchInterface $current_route_match, AccountInterface $user, EntityTypeManagerInterface $entity_type_manager, GroupPermissionsHashGeneratorInterface $hash_generator) {
-    parent::__construct($current_route_match, $user, $entity_type_manager);
-    $this->permissionsHashGenerator = $hash_generator;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t("Group membership permissions");
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    // If there was no existing group on the route, there can be no membership.
-    if (!$this->hasExistingGroup()) {
-      return 'none';
-    }
-
-    return $this->permissionsHashGenerator->generate($this->group, $this->user);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheableMetadata() {
-    $cacheable_metadata = new CacheableMetadata();
-
-    // If any of the membership's roles are updated, it could mean the list of
-    // permissions changed as well. We therefore need to set the membership's
-    // roles' cacheable metadata.
-    //
-    // Note that we do not set the membership's cacheable metadata because that
-    // one is taken care of in the parent 'group_membership.roles' context.
-    if ($this->hasExistingGroup()) {
-      // Retrieve all of the group roles the user may get for the group.
-      $group_roles = $this->groupRoleStorage()->loadByUserAndGroup($this->user, $this->group);
-
-      // Merge the cacheable metadata of all the roles.
-      foreach ($group_roles as $group_role) {
-        $group_role_cacheable_metadata = new CacheableMetadata();
-        $group_role_cacheable_metadata->createFromObject($group_role);
-        $cacheable_metadata->merge($group_role_cacheable_metadata);
-      }
-    }
-
-    return $cacheable_metadata;
-  }
-
-}
diff --git a/web/modules/group/src/Cache/Context/GroupMembershipRolesCacheContext.php b/web/modules/group/src/Cache/Context/GroupMembershipRolesCacheContext.php
deleted file mode 100644
index 2bf913b307..0000000000
--- a/web/modules/group/src/Cache/Context/GroupMembershipRolesCacheContext.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-namespace Drupal\group\Cache\Context;
-
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\Cache\Context\CalculatedCacheContextInterface;
-
-/**
- * Defines a cache context for "per group membership roles" caching.
- *
- * Only use this cache context when checking explicitly for certain roles. For
- * instance when you want to show a block listing all of the member's roles. Use
- * group_membership.roles.permissions for anything that checks permissions.
- *
- * Please note: This cache context uses the group from the current route as the
- * value object to work with. This context is therefore only to be used with
- * data that was based on the group from the route. You can retrieve it using
- * the 'entity:group' context provided by the 'group.group_route_context'
- * service. See an example at: \Drupal\group\Plugin\Block\GroupOperationsBlock.
- *
- * Cache context ID: 'group_membership.roles' (to vary by all roles).
- * Calculated cache context ID: 'group_membership.roles:%group_role', e.g.
- * 'group_membership.roles:%administrator' (to vary by the presence or absence
- * of the 'administrator' group role).
- */
-class GroupMembershipRolesCacheContext extends GroupMembershipCacheContextBase implements CalculatedCacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Group membership roles');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext($group_role = NULL) {
-    // If there was no existing group on the route, there can be no membership.
-    // As a consequence, there can be no group role. We need to make sure we
-    // return an invalid group role ID to avoid collisions.
-    if (!$this->hasExistingGroup()) {
-      return '...none...';
-    }
-
-    // Retrieve all of the group roles the user may get for the group.
-    $group_roles = $this->groupRoleStorage()->loadByUserAndGroup($this->user, $this->group);
-
-    if ($group_role === NULL) {
-      return implode(',', array_keys($group_roles));
-    }
-    else {
-      return isset($group_roles[$group_role]) ? '0' : '1';
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheableMetadata($group_role = NULL) {
-    $cacheable_metadata =  new CacheableMetadata();
-
-    // If the membership is updated, it could mean the list of roles changed as
-    // well. We therefore need to set the membership's cacheable metadata.
-    if ($this->hasExistingGroup()) {
-      if ($group_membership = $this->group->getMember($this->user)) {
-        $cacheable_metadata->createFromObject($group_membership);
-      }
-    }
-
-    return $cacheable_metadata;
-  }
-
-}
diff --git a/web/modules/group/src/Cache/Context/GroupTypeCacheContext.php b/web/modules/group/src/Cache/Context/GroupTypeCacheContext.php
deleted file mode 100644
index 9cafe41285..0000000000
--- a/web/modules/group/src/Cache/Context/GroupTypeCacheContext.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-namespace Drupal\group\Cache\Context;
-
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\Cache\Context\CacheContextInterface;
-
-/**
- * Defines a cache context for "per group type" caching.
- *
- * Please note: This cache context uses the group from the current route as the
- * value object to work with. This context is therefore only to be used with
- * data that was based on the group from the route. You can retrieve it using
- * the 'entity:group' context provided by the 'group.group_route_context'
- * service. See an example at: \Drupal\group\Plugin\Block\GroupOperationsBlock.
- *
- * Cache context ID: 'group.type'.
- */
-class GroupTypeCacheContext extends GroupCacheContextBase implements CacheContextInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getLabel() {
-    return t('Group type');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContext() {
-    return !empty($this->group) ? $this->group->bundle() : '';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheableMetadata() {
-    // You can't update a group type's ID and neither can you change a group's
-    // type. So if this cache context gets optimized away, we don't need to set
-    // any cache tags.
-    return new CacheableMetadata();
-  }
-
-}
diff --git a/web/modules/group/src/Context/GroupRouteContext.php b/web/modules/group/src/Context/GroupRouteContext.php
deleted file mode 100644
index dea1e37423..0000000000
--- a/web/modules/group/src/Context/GroupRouteContext.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-namespace Drupal\group\Context;
-
-use Drupal\Core\Cache\CacheableMetadata;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
-use Drupal\Core\Plugin\Context\ContextProviderInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-
-/**
- * Sets the current group as a context on group routes.
- */
-class GroupRouteContext implements ContextProviderInterface {
-
-  use GroupRouteContextTrait;
-  use StringTranslationTrait;
-
-  /**
-   * Constructs a new GroupRouteContext.
-   *
-   * @param \Drupal\Core\Routing\RouteMatchInterface $current_route_match
-   *   The current route match object.
-   */
-  public function __construct(RouteMatchInterface $current_route_match) {
-    $this->currentRouteMatch = $current_route_match;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getRuntimeContexts(array $unqualified_context_ids) {
-    // Create an optional context definition for group entities.
-    $context_definition = new ContextDefinition('entity:group', NULL, FALSE);
-
-    // Cache this context on the route.
-    $cacheability = new CacheableMetadata();
-    $cacheability->setCacheContexts(['route']);
-
-    // Create a context from the definition and retrieved or created group.
-    $context = new Context($context_definition, $this->getGroupFromRoute());
-    $context->addCacheableDependency($cacheability);
-
-    return ['group' => $context];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getAvailableContexts() {
-    $context = new Context(new ContextDefinition('entity:group', $this->t('Group from URL')));
-    return ['group' => $context];
-  }
-
-}
diff --git a/web/modules/group/src/Context/GroupRouteContextTrait.php b/web/modules/group/src/Context/GroupRouteContextTrait.php
deleted file mode 100644
index 53a6ac9199..0000000000
--- a/web/modules/group/src/Context/GroupRouteContextTrait.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-namespace Drupal\group\Context;
-
-use Drupal\group\Entity\Group;
-use Drupal\group\Entity\GroupInterface;
-
-/**
- * Trait to get the group entity from the current route.
- *
- * Using this trait will add the getGroupFromRoute() method to the class.
- *
- * If the class is capable of injecting services from the container, it should
- * inject the 'current_route_match' service and assign it to the
- * $this->currentRouteMatch property.
- */
-trait GroupRouteContextTrait {
-
-  /**
-   * The current route match object.
-   *
-   * @var \Drupal\Core\Routing\RouteMatchInterface
-   */
-  protected $currentRouteMatch;
-
-  /**
-   * Gets the current route match object.
-   *
-   * @return \Drupal\Core\Routing\RouteMatchInterface
-   *   The current route match object.
-   */
-  protected function getCurrentRouteMatch() {
-    if (!$this->currentRouteMatch) {
-      $this->currentRouteMatch = \Drupal::service('current_route_match');
-    }
-    return $this->currentRouteMatch;
-  }
-
-  /**
-   * Retrieves the group entity from the current route.
-   *
-   * This will try to load the group entity from the route if present. If we are
-   * on the group add form, it will return a new group entity with the group
-   * type set.
-   *
-   * @return \Drupal\group\Entity\GroupInterface|null
-   *   A group entity if one could be found or created, NULL otherwise.
-   */
-  public function getGroupFromRoute() {
-    $route_match = $this->getCurrentRouteMatch();
-    
-    // See if the route has a group parameter and try to retrieve it.
-    if (($group = $route_match->getParameter('group')) && $group instanceof GroupInterface) {
-      return $group;
-    }
-    // Create a new group to use as context if on the group add form.
-    elseif ($route_match->getRouteName() == 'entity.group.add_form') {
-      $group_type = $route_match->getParameter('group_type');
-      return Group::create(['type' => $group_type->id()]);
-    }
-
-    return NULL;
-  }
-
-}
diff --git a/web/modules/group/src/Controller/GroupMembershipController.php b/web/modules/group/src/Controller/GroupMembershipController.php
deleted file mode 100644
index 75ad79f717..0000000000
--- a/web/modules/group/src/Controller/GroupMembershipController.php
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-
-namespace Drupal\group\Controller;
-
-use Drupal\Core\Controller\ControllerBase;
-use Drupal\Core\Entity\EntityFormBuilderInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupContent;
-use Drupal\group\Entity\GroupInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides group membership route controllers.
- *
- * This only controls the routes that are not supported out of the box by the
- * plugin base \Drupal\group\Plugin\GroupContentEnablerBase.
- */
-class GroupMembershipController extends ControllerBase {
-
-  /**
-   * The current user.
-   *
-   * @var \Drupal\Core\Session\AccountInterface
-   */
-  protected $currentUser;
-  
-  /**
-   * The entity form builder.
-   *
-   * @var \Drupal\Core\Entity\EntityFormBuilderInterface
-   */
-  protected $entityFormBuilder;
-  
-  /**
-   * Constructs a new GroupMembershipController.
-   *
-   * @param \Drupal\Core\Session\AccountInterface $current_user
-   *   The current user.
-   * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entity_form_builder
-   *   The entity form builder.
-   */
-  public function __construct(AccountInterface $current_user, EntityFormBuilderInterface $entity_form_builder) {
-    $this->currentUser = $current_user;
-    $this->entityFormBuilder = $entity_form_builder;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('current_user'),
-      $container->get('entity.form_builder')
-    );
-  }
-
-  /**
-   * Provides the form for joining a group.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to join.
-   *
-   * @return array
-   *   A group join form.
-   */
-  public function join(GroupInterface $group) {
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    $plugin = $group->getGroupType()->getContentPlugin('group_membership');
-
-    // Pre-populate a group membership with the current user.
-    $group_content = GroupContent::create([
-      'type' => $plugin->getContentTypeConfigId(),
-      'gid' => $group->id(),
-      'entity_id' => $this->currentUser->id(),
-    ]);
-
-    return $this->entityFormBuilder->getForm($group_content, 'group-join');
-  }
-
-  /**
-   * The _title_callback for the join form route.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to join.
-   *
-   * @return string
-   *   The page title.
-   */
-  public function joinTitle(GroupInterface $group) {
-    return $this->t('Join group %label', ['%label' => $group->label()]);
-  }
-
-  /**
-   * Provides the form for leaving a group.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to leave.
-   *
-   * @return array
-   *   A group leave form.
-   */
-  public function leave(GroupInterface $group) {
-    $group_content = $group->getMember($this->currentUser)->getGroupContent();
-    return $this->entityFormBuilder->getForm($group_content, 'group-leave');
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Access/GroupAccessControlHandler.php b/web/modules/group/src/Entity/Access/GroupAccessControlHandler.php
deleted file mode 100644
index 03f7838fac..0000000000
--- a/web/modules/group/src/Entity/Access/GroupAccessControlHandler.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Access;
-
-use Drupal\group\Access\GroupAccessResult;
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Entity\EntityAccessControlHandler;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Access controller for the Group entity.
- *
- * @see \Drupal\group\Entity\Group.
- */
-class GroupAccessControlHandler extends EntityAccessControlHandler {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
-    switch ($operation) {
-      case 'view':
-        return GroupAccessResult::allowedIfHasGroupPermission($entity, $account, 'view group');
-
-      case 'update':
-        return GroupAccessResult::allowedIfHasGroupPermission($entity, $account, 'edit group');
-
-      case 'delete':
-        return GroupAccessResult::allowedIfHasGroupPermission($entity, $account, 'delete group');
-    }
-
-    return AccessResult::neutral();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
-    $permissions = ['bypass group access', 'create ' . $entity_bundle . ' group'];
-    return AccessResult::allowedIfHasPermissions($account, $permissions, 'OR');
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Access/GroupContentAccessControlHandler.php b/web/modules/group/src/Entity/Access/GroupContentAccessControlHandler.php
deleted file mode 100644
index fd69e16c12..0000000000
--- a/web/modules/group/src/Entity/Access/GroupContentAccessControlHandler.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Access;
-
-use Drupal\group\Entity\GroupContentType;
-use Drupal\Core\Entity\EntityAccessControlHandler;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Access controller for the Group entity.
- *
- * @see \Drupal\group\Entity\Group.
- */
-class GroupContentAccessControlHandler extends EntityAccessControlHandler {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
-    /** @var \Drupal\group\Entity\GroupContentInterface $entity */
-    return $entity->getContentPlugin()->checkAccess($entity, $operation, $account);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
-    $group_content_type = GroupContentType::load($entity_bundle);
-    return $group_content_type->getContentPlugin()->createAccess($context['group'], $account);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Access/GroupContentTypeAccessControlHandler.php b/web/modules/group/src/Entity/Access/GroupContentTypeAccessControlHandler.php
deleted file mode 100644
index 2a87b301d9..0000000000
--- a/web/modules/group/src/Entity/Access/GroupContentTypeAccessControlHandler.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Access;
-
-use Drupal\Core\Entity\EntityAccessControlHandler;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Defines the access control handler for the group content type entity type.
- *
- * @see \Drupal\group\Entity\GroupContentType
- */
-class GroupContentTypeAccessControlHandler extends EntityAccessControlHandler {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
-    /** @var \Drupal\group\Entity\GroupContentTypeInterface $entity */
-    if ($operation == 'delete') {
-      return parent::checkAccess($entity, $operation, $account)->addCacheableDependency($entity);
-    }
-    return parent::checkAccess($entity, $operation, $account);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Access/GroupRoleAccessControlHandler.php b/web/modules/group/src/Entity/Access/GroupRoleAccessControlHandler.php
deleted file mode 100644
index a3a3ab6259..0000000000
--- a/web/modules/group/src/Entity/Access/GroupRoleAccessControlHandler.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Access;
-
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Entity\EntityAccessControlHandler;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Defines the access control handler for the group role entity type.
- *
- * @see \Drupal\group\Entity\GroupRole
- */
-class GroupRoleAccessControlHandler extends EntityAccessControlHandler {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
-    /** @var \Drupal\group\Entity\GroupRoleInterface $entity */
-    if ($operation == 'delete') {
-      return parent::checkAccess($entity, $operation, $account)->addCacheableDependency($entity);
-    }
-    
-    // Group roles have no 'view' route but may be used in views to show what
-    // roles a member has. We therefore allow 'view' access so field formatters
-    // such as entity_reference_label will work.
-    if ($operation == 'view') {
-      return AccessResult::allowed()->addCacheableDependency($entity);
-    }
-    
-    return parent::checkAccess($entity, $operation, $account);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Access/GroupTypeAccessControlHandler.php b/web/modules/group/src/Entity/Access/GroupTypeAccessControlHandler.php
deleted file mode 100644
index fd9fa615c0..0000000000
--- a/web/modules/group/src/Entity/Access/GroupTypeAccessControlHandler.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Access;
-
-use Drupal\Core\Access\AccessResult;
-use Drupal\Core\Entity\EntityAccessControlHandler;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Defines the access control handler for the group type entity type.
- *
- * @see \Drupal\group\Entity\GroupType
- */
-class GroupTypeAccessControlHandler extends EntityAccessControlHandler {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
-    /** @var \Drupal\group\Entity\GroupTypeInterface $entity */
-    if ($operation == 'delete') {
-      return parent::checkAccess($entity, $operation, $account)->addCacheableDependency($entity);
-    }
-
-    // Group types have no 'view' route but may be used in views to show what
-    // type a group is. We therefore allow 'view' access so field formatters
-    // such as entity_reference_label will work.
-    if ($operation == 'view') {
-      return AccessResult::allowed()->addCacheableDependency($entity);
-    }
-
-    return parent::checkAccess($entity, $operation, $account);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Controller/GroupContentController.php b/web/modules/group/src/Entity/Controller/GroupContentController.php
deleted file mode 100644
index 71e40fddd1..0000000000
--- a/web/modules/group/src/Entity/Controller/GroupContentController.php
+++ /dev/null
@@ -1,392 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Controller;
-
-use Drupal\Core\Controller\ControllerBase;
-use Drupal\Core\Entity\EntityFormBuilderInterface;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Link;
-use Drupal\Core\Render\RendererInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Url;
-use Drupal\group\Entity\GroupContentType;
-use Drupal\group\Entity\GroupInterface;
-use Drupal\user\PrivateTempStoreFactory;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\HttpFoundation\RedirectResponse;
-
-/**
- * Returns responses for GroupContent routes.
- */
-class GroupContentController extends ControllerBase {
-
-  /**
-   * The private store factory.
-   *
-   * @var \Drupal\user\PrivateTempStoreFactory
-   */
-  protected $privateTempStoreFactory;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The entity form builder.
-   *
-   * @var \Drupal\Core\Entity\EntityFormBuilderInterface
-   */
-  protected $entityFormBuilder;
-
-  /**
-   * The renderer.
-   *
-   * @var \Drupal\Core\Render\RendererInterface
-   */
-  protected $renderer;
-
-  /**
-   * Constructs a new GroupContentController.
-   *
-   * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
-   *   The private store factory.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entity_form_builder
-   *   The entity form builder.
-   * @param \Drupal\Core\Render\RendererInterface $renderer
-   *   The renderer.
-   */
-  public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityTypeManagerInterface $entity_type_manager, EntityFormBuilderInterface $entity_form_builder, RendererInterface $renderer) {
-    $this->privateTempStoreFactory = $temp_store_factory;
-    $this->entityTypeManager = $entity_type_manager;
-    $this->entityFormBuilder = $entity_form_builder;
-    $this->renderer = $renderer;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('user.private_tempstore'),
-      $container->get('entity_type.manager'),
-      $container->get('entity.form_builder'),
-      $container->get('renderer')
-    );
-  }
-
-  /**
-   * Provides the group content creation overview page.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to add the group content to.
-   * @param bool $create_mode
-   *   (optional) Whether the target entity still needs to be created. Defaults
-   *   to FALSE, meaning the target entity is assumed to exist already.
-   *
-   * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
-   *   The group content creation overview page or a redirect to the form for
-   *   adding group content if there is only one group content type.
-   */
-  public function addPage(GroupInterface $group, $create_mode = FALSE) {
-    $build = ['#theme' => 'entity_add_list', '#bundles' => []];
-    $form_route = $this->addPageFormRoute($group, $create_mode);
-    $bundle_names = $this->addPageBundles($group, $create_mode);
-
-    // Set the add bundle message if available.
-    $add_bundle_message = $this->addPageBundleMessage($group, $create_mode);
-    if ($add_bundle_message !== FALSE) {
-      $build['#add_bundle_message'] = $add_bundle_message;
-    }
-
-    // Filter out the bundles the user doesn't have access to.
-    $access_control_handler = $this->entityTypeManager->getAccessControlHandler('group_content');
-    foreach ($bundle_names as $plugin_id => $bundle_name) {
-      $access = $access_control_handler->createAccess($bundle_name, NULL, ['group' => $group], TRUE);
-      if (!$access->isAllowed()) {
-        unset($bundle_names[$plugin_id]);
-      }
-      $this->renderer->addCacheableDependency($build, $access);
-    }
-
-    // Redirect if there's only one bundle available.
-    if (count($bundle_names) == 1) {
-      reset($bundle_names);
-      $route_params = ['group' => $group->id(), 'plugin_id' => key($bundle_names)];
-      $url = Url::fromRoute($form_route, $route_params, ['absolute' => TRUE]);
-      return new RedirectResponse($url->toString());
-    }
-
-    // Set the info for all of the remaining bundles.
-    foreach ($bundle_names as $plugin_id => $bundle_name) {
-      $plugin = $group->getGroupType()->getContentPlugin($plugin_id);
-      $label = $plugin->getLabel();
-
-      $build['#bundles'][$bundle_name] = [
-        'label' => $label,
-        'description' => $plugin->getContentTypeDescription(),
-        'add_link' => Link::createFromRoute($label, $form_route, ['group' => $group->id(), 'plugin_id' => $plugin_id]),
-      ];
-    }
-
-    // Add the list cache tags for the GroupContentType entity type.
-    $bundle_entity_type = $this->entityTypeManager->getDefinition('group_content_type');
-    $build['#cache']['tags'] = $bundle_entity_type->getListCacheTags();
-
-    return $build;
-  }
-
-  /**
-   * Retrieves a list of available bundles for the add page.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to add the group content to.
-   * @param bool $create_mode
-   *   Whether the target entity still needs to be created.
-   *
-   * @return array
-   *   An array of group content type IDs, keyed by the plugin that was used to
-   *   generate their respective group content types.
-   *
-   * @see ::addPage()
-   */
-  protected function addPageBundles(GroupInterface $group, $create_mode) {
-    $bundles = [];
-
-    /** @var \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface $storage */
-    $storage = $this->entityTypeManager->getStorage('group_content_type');
-    foreach ($storage->loadByGroupType($group->getGroupType()) as $bundle => $group_content_type) {
-      // Skip the bundle if we are listing bundles that allow you to create an
-      // entity in the group and the bundle's plugin does not support that.
-      if ($create_mode && !$group_content_type->getContentPlugin()->definesEntityAccess()) {
-        continue;
-      }
-
-      $bundles[$group_content_type->getContentPluginId()] = $bundle;
-    }
-
-    return $bundles;
-  }
-
-  /**
-   * Returns the 'add_bundle_message' string for the add page.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to add the group content to.
-   * @param bool $create_mode
-   *   Whether the target entity still needs to be created.
-   *
-   * @return string|false
-   *   The translated string or FALSE if no string should be set.
-   *
-   * @see ::addPage()
-   */
-  protected function addPageBundleMessage(GroupInterface $group, $create_mode) {
-    // We do not set the 'add_bundle_message' variable because we deny access to
-    // the page if no bundle is available. This method exists so that modules
-    // that extend this controller may specify a message should they decide to
-    // allow access to their page even if it has no bundles.
-    return FALSE;
-  }
-
-  /**
-   * Returns the route name of the form the add page should link to.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to add the group content to.
-   * @param bool $create_mode
-   *   Whether the target entity still needs to be created.
-   *
-   * @return string
-   *   The route name.
-   *
-   * @see ::addPage()
-   */
-  protected function addPageFormRoute(GroupInterface $group, $create_mode) {
-    return $create_mode
-      ? 'entity.group_content.create_form'
-      : 'entity.group_content.add_form';
-  }
-
-  /**
-   * Provides the group content submission form.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to add the group content to.
-   * @param string $plugin_id
-   *   The group content enabler to add content with.
-   *
-   * @return array
-   *   A group submission form.
-   */
-  public function addForm(GroupInterface $group, $plugin_id) {
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    $plugin = $group->getGroupType()->getContentPlugin($plugin_id);
-
-    $values = [
-      'type' => $plugin->getContentTypeConfigId(),
-      'gid' => $group->id(),
-    ];
-    $group_content = $this->entityTypeManager()->getStorage('group_content')->create($values);
-
-    return $this->entityFormBuilder->getForm($group_content, 'add');
-  }
-
-  /**
-   * The _title_callback for the entity.group_content.add_form route.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to add the group content to.
-   * @param string $plugin_id
-   *   The group content enabler to add content with.
-   *
-   * @return string
-   *   The page title.
-   */
-  public function addFormTitle(GroupInterface $group, $plugin_id) {
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    $plugin = $group->getGroupType()->getContentPlugin($plugin_id);
-    $group_content_type = GroupContentType::load($plugin->getContentTypeConfigId());
-    return $this->t('Create @name', ['@name' => $group_content_type->label()]);
-  }
-
-  /**
-   * The _title_callback for the entity.group_content.edit_form route.
-   *
-   * Overrides the Drupal\Core\Entity\Controller\EntityController::editTitle().
-   *
-   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
-   *   The route match.
-   * @param \Drupal\Core\Entity\EntityInterface $_entity
-   *   (optional) An entity, passed in directly from the request attributes.
-   *
-   * @return string|null
-   *   The title for the entity edit page, if an entity was found.
-   */
-  public function editFormTitle(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
-    if ($entity = $route_match->getParameter('group_content')) {
-      return $this->t('Edit %label', ['%label' => $entity->label()]);
-    }
-  }
-
-  /**
-   * The _title_callback for the entity.group_content.collection route.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to add the group content to.
-   *
-   * @return string
-   *   The page title.
-   *
-   * @todo Revisit when 8.2.0 is released, https://www.drupal.org/node/2767853.
-   */
-  public function collectionTitle(GroupInterface $group) {
-    return $this->t('Related entities for @group', ['@group' => $group->label()]);
-  }
-
-  /**
-   * Provides the group content creation form.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to add the group content to.
-   * @param string $plugin_id
-   *   The group content enabler to add content with.
-   *
-   * @return array
-   *   A group content creation form.
-   */
-  public function createForm(GroupInterface $group, $plugin_id) {
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    $plugin = $group->getGroupType()->getContentPlugin($plugin_id);
-
-    $store = $this->privateTempStoreFactory->get('group_content_wizard');
-    $store_id = $plugin_id . ':' . $group->id();
-
-    // See if the plugin uses a wizard for creating new entities.
-    $config = $plugin->getConfiguration();
-    $wizard = $config['use_creation_wizard'];
-
-    // See if we are on the second step of the form.
-    $step2 = $wizard && $store->get("$store_id:step") === 2;
-
-    // Content entity form, potentially as wizard step 1.
-    if (!$step2) {
-      // Figure out what entity type the plugin is serving.
-      $entity_type_id = $plugin->getEntityTypeId();
-      $entity_type = $this->entityTypeManager()->getDefinition($entity_type_id);
-      $storage = $this->entityTypeManager()->getStorage($entity_type_id);
-
-      // Only create a new entity if we have nothing stored.
-      if (!$entity = $store->get("$store_id:entity")) {
-        $values = [];
-        if (($key = $entity_type->getKey('bundle')) && ($bundle = $plugin->getEntityBundle())) {
-          $values[$key] = $bundle;
-        }
-        $entity = $storage->create($values);
-      }
-
-      // Use the add form handler if available.
-      $operation = 'default';
-      if ($entity_type->getFormClass('add')) {
-        $operation = 'add';
-      }
-
-      // Pass the group and plugin ID to the form state.
-      $extra = [
-        'group' => $group,
-        'group_content_enabler' => $plugin_id,
-      ];
-
-      // If we are in a wizard, we'll also need to pass the temp store ID.
-      if ($wizard) {
-        $extra['store_id'] = $store_id;
-      }
-
-      // Return the entity form with the configuration gathered above.
-      return $this->entityFormBuilder()->getForm($entity, $operation, $extra);
-    }
-    // Wizard step 2: Group content form.
-    else {
-      // Create an empty group content entity.
-      $values = [
-        'type' => $plugin->getContentTypeConfigId(),
-        'gid' => $group->id(),
-      ];
-      $group_content = $this->entityTypeManager()->getStorage('group_content')->create($values);
-
-      // Pass the group, plugin ID and storage ID to the form state.
-      $extra = [
-        'group' => $group,
-        'group_content_enabler' => $plugin_id,
-        'store_id' => $store_id,
-      ];
-
-      // Return the entity form with the configuration gathered above.
-      return $this->entityFormBuilder()->getForm($group_content, 'add', $extra);
-    }
-  }
-
-  /**
-   * The _title_callback for the entity.group_content.create_form route.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to create the group content in.
-   * @param string $plugin_id
-   *   The group content enabler to create content with.
-   *
-   * @return string
-   *   The page title.
-   */
-  public function createFormTitle(GroupInterface $group, $plugin_id) {
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    $plugin = $group->getGroupType()->getContentPlugin($plugin_id);
-    $group_content_type = GroupContentType::load($plugin->getContentTypeConfigId());
-    return $this->t('Create @name', ['@name' => $group_content_type->label()]);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Controller/GroupContentListBuilder.php b/web/modules/group/src/Entity/Controller/GroupContentListBuilder.php
deleted file mode 100644
index 9c219cbdc2..0000000000
--- a/web/modules/group/src/Entity/Controller/GroupContentListBuilder.php
+++ /dev/null
@@ -1,163 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Controller;
-
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\EntityListBuilder;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Routing\RedirectDestinationInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides a list controller for group content entities.
- *
- * @ingroup group
- */
-class GroupContentListBuilder extends EntityListBuilder {
-
-  /**
-   * The group to show the content for.
-   *
-   * @var \Drupal\group\Entity\GroupInterface
-   */
-  protected $group;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Routing\RedirectDestinationInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The redirect destination.
-   *
-   * @var \Drupal\Core\Routing\RedirectDestinationInterface
-   */
-  protected $redirectDestination;
-
-  /**
-   * Constructs a new GroupContentListBuilder object.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
-   *   The redirect destination.
-   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
-   *   The route match.
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
-   *   The entity type definition.
-   */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager, RedirectDestinationInterface $redirect_destination, RouteMatchInterface $route_match, EntityTypeInterface $entity_type) {
-    parent::__construct($entity_type, $entity_type_manager->getStorage($entity_type->id()));
-    $this->entityTypeManager = $entity_type_manager;
-    $this->redirectDestination = $redirect_destination;
-    // There should always be a group on the route for group content lists.
-    $this->group = $route_match->getParameters()->get('group');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
-    return new static(
-      $container->get('entity_type.manager'),
-      $container->get('redirect.destination'),
-      $container->get('current_route_match'),
-      $entity_type
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getEntityIds() {
-    $query = $this->getStorage()->getQuery();
-    $query->sort($this->entityType->getKey('id'));
-
-    // Only show group content for the group on the route.
-    $query->condition('gid', $this->group->id());
-
-    // Only add the pager if a limit is specified.
-    if ($this->limit) {
-      $query->pager($this->limit);
-    }
-
-    return $query->execute();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildHeader() {
-    $header = [
-      'id' => $this->t('ID'),
-      'label' => $this->t('Content label'),
-      'entity_type' => $this->t('Entity type'),
-      'plugin' => $this->t('Plugin used'),
-    ];
-    return $header + parent::buildHeader();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildRow(EntityInterface $entity) {
-    /** @var \Drupal\group\Entity\GroupContentInterface $entity */
-    $row['id'] = $entity->id();
-
-    // EntityListBuilder sets the table rows using the #rows property, so we
-    // need to add links as render arrays using the 'data' key.
-    $row['label']['data'] = $entity->toLink()->toRenderable();
-    $entity_type_id = $entity->getContentPlugin()->getEntityTypeId();
-    $row['entity_type'] = $this->entityTypeManager->getDefinition($entity_type_id)->getLabel();
-    $row['plugin'] = $entity->getContentPlugin()->getLabel();
-
-    return $row + parent::buildRow($entity);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function render() {
-    $build = parent::render();
-    $build['table']['#empty'] = $this->t('There are no entities related to this group yet.');
-    return $build;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getDefaultOperations(EntityInterface $entity) {
-    /** @var \Drupal\group\Entity\GroupContentInterface $entity */
-    $operations = parent::getDefaultOperations($entity);
-
-    // Improve the edit and delete operation labels.
-    if (isset($operations['edit'])) {
-      $operations['edit']['title'] = $this->t('Edit relation');
-    }
-    if (isset($operations['delete'])) {
-      $operations['delete']['title'] = $this->t('Delete relation');
-    }
-
-    // Slap on redirect destinations for the administrative operations.
-    $destination = $this->redirectDestination->getAsArray();
-    foreach ($operations as $key => $operation) {
-      $operations[$key]['query'] = $destination;
-    }
-
-    // Add an operation to view the actual entity.
-    if ($entity->getEntity()->access('view') && $entity->getEntity()->hasLinkTemplate('canonical')) {
-      $operations['view'] = array(
-        'title' => $this->t('View related entity'),
-        'weight' => 101,
-        'url' => $entity->getEntity()->toUrl('canonical'),
-      );
-    }
-
-    return $operations;
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Controller/GroupListBuilder.php b/web/modules/group/src/Entity/Controller/GroupListBuilder.php
deleted file mode 100644
index fc81351115..0000000000
--- a/web/modules/group/src/Entity/Controller/GroupListBuilder.php
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Controller;
-
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\EntityListBuilder;
-use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Routing\RedirectDestinationInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides a list controller for group entities.
- *
- * @ingroup group
- */
-class GroupListBuilder extends EntityListBuilder {
-
-  /**
-   * The redirect destination service.
-   *
-   * @var \Drupal\Core\Routing\RedirectDestinationInterface
-   */
-  protected $redirectDestination;
-
-  /**
-   * Constructs a new GroupListBuilder object.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
-   *   The entity type definition.
-   * @param \Drupal\Core\Entity\EntityStorageInterface $storage
-   *   The entity storage class.
-   * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
-   *   The redirect destination service.
-   */
-  public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, RedirectDestinationInterface $redirect_destination) {
-    parent::__construct($entity_type, $storage);
-    $this->redirectDestination = $redirect_destination;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
-    return new static(
-      $entity_type,
-      $container->get('entity_type.manager')->getStorage($entity_type->id()),
-      $container->get('redirect.destination')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildHeader() {
-    $header['gid'] = $this->t('Group ID');
-    $header['name'] = $this->t('Name');
-    $header['type'] = $this->t('Type');
-    $header['uid'] = $this->t('Owner');
-    return $header + parent::buildHeader();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildRow(EntityInterface $entity) {
-    /** @var \Drupal\group\Entity\GroupInterface $entity */
-    $row['id'] = $entity->id();
-    // EntityListBuilder sets the table rows using the #rows property, so we
-    // need to add the render array using the 'data' key.
-    $row['name']['data'] = $entity->toLink()->toRenderable();
-    $row['type'] = $entity->getGroupType()->label();
-    $row['uid'] = $entity->uid->entity->label();
-    return $row + parent::buildRow($entity);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function render() {
-    $build = parent::render();
-    $build['table']['#empty'] = $this->t('There are no groups yet.');
-    return $build;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getDefaultOperations(EntityInterface $entity) {
-    $operations = parent::getDefaultOperations($entity);
-
-    // Add the current path or destination as a redirect to the operation links.
-    $destination = $this->redirectDestination->getAsArray();
-    foreach ($operations as $key => $operation) {
-      $operations[$key]['query'] = $destination;
-    }
-
-    return $operations;
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Controller/GroupRoleController.php b/web/modules/group/src/Entity/Controller/GroupRoleController.php
deleted file mode 100644
index 287489002d..0000000000
--- a/web/modules/group/src/Entity/Controller/GroupRoleController.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Controller;
-
-use Drupal\Core\Entity\Controller\EntityController;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-
-/**
- * Returns responses for GroupRole routes.
- */
-class GroupRoleController extends EntityController  {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function doGetEntity(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
-    if ($_entity) {
-      $entity = $_entity;
-    }
-    // The parent function will only grab the first entity from the route. In
-    // this case, that would incorrectly be the group type. We need to hard-code
-    // the group_role parameter until https://www.drupal.org/node/2827739 lands.
-    // @todo Keep an eye on https://www.drupal.org/node/2827739.
-    elseif ($route_match->getRawParameter('group_role') !== NULL) {
-      $entity = $route_match->getParameter('group_role');
-    }
-    if (isset($entity)) {
-      return $this->entityRepository->getTranslationFromContext($entity);
-    }
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Controller/GroupRoleListBuilder.php b/web/modules/group/src/Entity/Controller/GroupRoleListBuilder.php
deleted file mode 100644
index cae119b65b..0000000000
--- a/web/modules/group/src/Entity/Controller/GroupRoleListBuilder.php
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Controller;
-
-use Drupal\group\Entity\GroupTypeInterface;
-use Drupal\Core\Url;
-use Drupal\Core\Config\Entity\DraggableListBuilder;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Defines a class to build a listing of group role entities.
- *
- * @see \Drupal\group\Entity\GroupRole
- */
-class GroupRoleListBuilder extends DraggableListBuilder {
-
-  /**
-   * The group type to check for roles.
-   *
-   * @var GroupTypeInterface $groupType
-   */
-  protected $groupType;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, RouteMatchInterface $route_match) {
-    parent::__construct($entity_type, $storage);
-
-    // When on the default group role list route, we should have a group type.
-    if ($route_match->getRouteName() == 'entity.group_role.collection') {
-      $parameters = $route_match->getParameters();
-
-      // Check if the route had a group type parameter.
-      if ($parameters->has('group_type') && $group_type = $parameters->get('group_type')) {
-        if ($group_type instanceof GroupTypeInterface) {
-          $this->groupType = $group_type;
-        }
-      }
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
-    return new static(
-      $entity_type,
-      $container->get('entity.manager')->getStorage($entity_type->id()),
-      $container->get('current_route_match')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getEntityIds() {
-    $query = $this->getStorage()->getQuery()
-      ->condition('internal', 0, '=')
-      ->condition('group_type', $this->groupType->id(), '=')
-      ->sort($this->entityType->getKey('weight'));
-
-    // Only add the pager if a limit is specified.
-    if ($this->limit) {
-      $query->pager($this->limit);
-    }
-
-    return array_values($query->execute());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-    return 'group_admin_roles';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildHeader() {
-    $header['label'] = t('Name');
-    return $header + parent::buildHeader();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildRow(EntityInterface $entity) {
-    $row['label'] = $entity->label();
-    return $row + parent::buildRow($entity);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDefaultOperations(EntityInterface $entity) {
-    $operations = parent::getDefaultOperations($entity);
-
-    if ($entity->hasLinkTemplate('permissions-form')) {
-      $operations['permissions'] = [
-        'title' => t('Edit permissions'),
-        'weight' => 5,
-        'url' => $entity->toUrl('permissions-form'),
-      ];
-    }
-
-    return $operations;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function render() {
-    $build = parent::render();
-    $build['table']['#empty'] = $this->t('No group roles available. <a href="@link">Add group role</a>.', [
-      '@link' => Url::fromRoute('entity.group_role.add_form', ['group_type' => $this->groupType->id()])->toString()
-    ]);
-    return $build;
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Controller/GroupTypeController.php b/web/modules/group/src/Entity/Controller/GroupTypeController.php
deleted file mode 100644
index 54d6a82dc8..0000000000
--- a/web/modules/group/src/Entity/Controller/GroupTypeController.php
+++ /dev/null
@@ -1,257 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Controller;
-
-use Drupal\group\Entity\GroupTypeInterface;
-use Drupal\group\Entity\GroupContentType;
-use Drupal\group\Plugin\GroupContentEnablerInterface;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Drupal\Core\Url;
-use Drupal\Core\Controller\ControllerBase;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides the user permissions administration form for a specific group type.
- */
-class GroupTypeController extends ControllerBase {
-
-  /**
-   * The group type to use in this controller.
-   *
-   * @var \Drupal\group\Entity\GroupTypeInterface
-   */
-  protected $groupType;
-
-  /**
-   * The group content plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * The module manager.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * Constructs a new GroupTypeController.
-   *
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content plugin manager.
-   */
-  public function __construct(ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager, GroupContentEnablerManagerInterface $plugin_manager) {
-    $this->moduleHandler = $module_handler;
-    $this->entityTypeManager = $entity_type_manager;
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('module_handler'),
-      $container->get('entity_type.manager'),
-      $container->get('plugin.manager.group_content_enabler')
-    );
-  }
-
-  /**
-   * Builds an admin interface to manage the group type's group content plugins.
-   *
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   The group type to build an interface for.
-   *
-   * @return array
-   *   The render array for the page.
-   */
-  public function content(GroupTypeInterface $group_type) {
-    $this->groupType = $group_type;
-
-    // Render the table of available content enablers.
-    $page['system_compact_link'] = [
-      '#id' => FALSE,
-      '#type' => 'system_compact_link',
-    ];
-
-    $page['content'] = [
-      '#type' => 'table',
-      '#header' => [
-        'info' => $this->t('Plugin information'),
-        'provider' => $this->t('Provided by'),
-        'entity_type_id' => $this->t('Applies to'),
-        'status' => $this->t('Status'),
-        'operations' => $this->t('Operations'),
-      ],
-      '#suffix' =>  $this->t('<em>* These plugins are set to be always on by their providing module.</em>'),
-    ];
-
-    $installed = $this->pluginManager->getInstalledIds($group_type);
-    foreach ($this->pluginManager->getAll() as $plugin_id => $plugin) {
-      // If the plugin is installed on the group type, use that one instead of
-      // an 'empty' version so that we may use methods on it which expect to
-      // have a group type configured.
-      if (in_array($plugin_id, $installed)) {
-        $plugin = $this->groupType->getContentPlugin($plugin_id);
-      }
-      $page['content'][$plugin_id] = $this->buildRow($plugin);
-    }
-
-    return $page;
-  }
-
-  /**
-   * Builds a row for a content enabler plugin.
-   *
-   * @param \Drupal\group\Plugin\GroupContentEnablerInterface $plugin
-   *   The content enabler plugin to build operation links for.
-   *
-   * @return array
-   *   A render array to use as a table row.
-   */
-  public function buildRow(GroupContentEnablerInterface $plugin) {
-    $installed = $this->pluginManager->getInstalledIds($this->groupType);
-
-    // Get the plugin status.
-    if (in_array($plugin->getPluginId(), $installed)) {
-      $status = $this->t('Installed');
-
-      // Mark enforced plugins with an asterisk.
-      if ($plugin->isEnforced()) {
-        $status .= '*';
-      }
-    }
-    else {
-      $status = $this->t('Not installed');
-    }
-
-    $row = [
-      'info' => [
-        '#type' => 'inline_template',
-        '#template' => '<div class="description"><span class="label">{{ label }}</span>{% if description %}<br/>{{ description }}{% endif %}</div>',
-        '#context' => [
-          'label' => $plugin->getLabel(),
-        ],
-      ],
-      'provider' => [
-        '#markup' => $this->moduleHandler->getName($plugin->getProvider())
-      ],
-      'entity_type_id' => [
-        '#markup' => $this->entityTypeManager->getDefinition($plugin->getEntityTypeId())->getLabel()
-      ],
-      'status' => ['#markup' => $status],
-      'operations' => $this->buildOperations($plugin),
-    ];
-
-    // Show the content enabler description if toggled on.
-    if (!system_admin_compact_mode()) {
-      $row['info']['#context']['description'] = $plugin->getDescription();
-    }
-
-    return $row;
-  }
-
-  /**
-   * Provides an array of information to build a list of operation links.
-   *
-   * @param \Drupal\group\Plugin\GroupContentEnablerInterface $plugin
-   *   The content enabler plugin to build operation links for.
-   *
-   * @return array
-   *   An associative array of operation links for the group type's content
-   *   plugin, keyed by operation name, containing the following key-value pairs:
-   *   - title: The localized title of the operation.
-   *   - url: An instance of \Drupal\Core\Url for the operation URL.
-   *   - weight: The weight of this operation.
-   */
-  public function getOperations($plugin) {
-    return $plugin->getOperations() + $this->getDefaultOperations($plugin);
-  }
-
-  /**
-   * Gets the group type's content plugin's default operation links.
-   *
-   * @param \Drupal\group\Plugin\GroupContentEnablerInterface $plugin
-   *   The content enabler plugin to build operation links for.
-   *
-   * @return array
-   *   The array structure is identical to the return value of
-   *   self::getOperations().
-   */
-  protected function getDefaultOperations($plugin) {
-    $operations = [];
-
-    $plugin_id = $plugin->getPluginId();
-    $installed = $this->pluginManager->getInstalledIds($this->groupType);
-
-    if (in_array($plugin_id, $installed)) {
-      /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-      $group_content_type_id = $plugin->getContentTypeConfigId();
-      $group_content_type = GroupContentType::load($group_content_type_id);
-
-      $route_params = [
-        'group_content_type' => $group_content_type_id,
-      ];
-
-      $operations['configure'] = [
-        'title' => $this->t('Configure'),
-        'url' => new Url('entity.group_content_type.edit_form', $route_params),
-      ];
-
-      if (!$plugin->isEnforced()) {
-        $operations['uninstall'] = [
-          'title' => $this->t('Uninstall'),
-          'weight' => 99,
-          'url' => new Url('entity.group_content_type.delete_form', $route_params),
-        ];
-      }
-
-      if ($this->moduleHandler->moduleExists('field_ui')) {
-        $operations += field_ui_entity_operation($group_content_type);
-      }
-    }
-    elseif (!$plugin->isEnforced()) {
-      $operations['install'] = [
-        'title' => $this->t('Install'),
-        'url' => new Url('entity.group_content_type.add_form', ['group_type' => $this->groupType->id(), 'plugin_id' => $plugin_id]),
-      ];
-    }
-
-    return $operations;
-  }
-
-  /**
-   * Builds operation links for the group type's content plugins.
-   *
-   * @param \Drupal\group\Plugin\GroupContentEnablerInterface $plugin
-   *   The content enabler plugin to build operation links for.
-   *
-   * @return array
-   *   A render array of operation links.
-   */
-  public function buildOperations($plugin) {
-    $build = [
-      '#type' => 'operations',
-      '#links' => $this->getOperations($plugin),
-    ];
-
-    return $build;
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Controller/GroupTypeListBuilder.php b/web/modules/group/src/Entity/Controller/GroupTypeListBuilder.php
deleted file mode 100644
index 1b0e1902cc..0000000000
--- a/web/modules/group/src/Entity/Controller/GroupTypeListBuilder.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Controller;
-
-use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
-use Drupal\Core\Url;
-use Drupal\Core\Entity\EntityInterface;
-
-/**
- * Defines a class to build a listing of group type entities.
- *
- * @see \Drupal\group\Entity\GroupType
- */
-class GroupTypeListBuilder extends ConfigEntityListBuilder {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildHeader() {
-    $header['label'] = t('Name');
-    $header['description'] = [
-      'data' => t('Description'),
-      'class' => [RESPONSIVE_PRIORITY_MEDIUM],
-    ];
-    return $header + parent::buildHeader();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildRow(EntityInterface $entity) {
-    /** @var \Drupal\group\Entity\GroupTypeInterface $entity */
-    $row['label'] = [
-      'data' => $entity->label(),
-      'class' => ['menu-label'],
-    ];
-    $row['description']['data'] = ['#markup' => $entity->getDescription()];
-    return $row + parent::buildRow($entity);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDefaultOperations(EntityInterface $entity) {
-    $operations = parent::getDefaultOperations($entity);
-    // Place the group type specific operations after the operations added by
-    // field_ui.module which have the weights 15, 20, 25.
-    if (isset($operations['edit'])) {
-      $operations['edit']['weight'] = 30;
-    }
-
-    if ($entity->hasLinkTemplate('permissions-form')) {
-      $operations['permissions'] = [
-        'title' => t('Edit permissions'),
-        'weight' => 35,
-        'url' => $entity->toUrl('permissions-form'),
-      ];
-    }
-
-    // Can't use a link template because the group roles route doesn't start
-    // with entity.group_type, see: https://www.drupal.org/node/2645136.
-    $operations['group_roles'] = [
-      'title' => t('Edit group roles'),
-      'weight' => 40,
-      'url' => Url::fromRoute('entity.group_role.collection', ['group_type' => $entity->id()]),
-    ];
-
-    if ($entity->hasLinkTemplate('content-plugins')) {
-      $operations['content'] = [
-        'title' => t('Set available content'),
-        'weight' => 45,
-        'url' => $entity->toUrl('content-plugins'),
-      ];
-    }
-
-    return $operations;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function render() {
-    $build = parent::render();
-    $build['table']['#empty'] = $this->t('No group types available. <a href="@link">Add group type</a>.', [
-      '@link' => Url::fromRoute('entity.group_type.add_form')->toString()
-    ]);
-    return $build;
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupContentDeleteForm.php b/web/modules/group/src/Entity/Form/GroupContentDeleteForm.php
deleted file mode 100644
index 6359c65b2a..0000000000
--- a/web/modules/group/src/Entity/Form/GroupContentDeleteForm.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Entity\ContentEntityConfirmFormBase;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Url;
-
-/**
- * Provides a form for deleting a group content entity.
- */
-class GroupContentDeleteForm extends ContentEntityConfirmFormBase {
-
-  /**
-   * Returns the plugin responsible for this piece of group content.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerInterface
-   *   The responsible group content enabler plugin.
-   */
-  protected function getContentPlugin() {
-    /** @var \Drupal\group\Entity\GroupContent $group_content */
-    $group_content = $this->getEntity();
-    return $group_content->getContentPlugin();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getQuestion() {
-    return $this->t('Are you sure you want to delete %name?', ['%name' => $this->entity->label()]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCancelURL() {
-    /** @var \Drupal\group\Entity\GroupContent $group_content */
-    $group_content = $this->getEntity();
-    $group = $group_content->getGroup();
-    $route_params = [
-      'group' => $group->id(),
-      'group_content' => $group_content->id(),
-    ];
-    return new Url('entity.group_content.canonical', $route_params);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getConfirmText() {
-    return $this->t('Delete');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-    /** @var \Drupal\group\Entity\GroupContent $group_content */
-    $group_content = $this->getEntity();
-    $group = $group_content->getGroup();
-    $group_content->delete();
-
-    \Drupal::logger('group_content')->notice('@type: deleted %title.', [
-      '@type' => $group_content->bundle(),
-      '%title' => $group_content->label(),
-    ]);
-
-    $form_state->setRedirect('entity.group.canonical', ['group' => $group->id()]);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupContentForm.php b/web/modules/group/src/Entity/Form/GroupContentForm.php
deleted file mode 100644
index 9f203c1a43..0000000000
--- a/web/modules/group/src/Entity/Form/GroupContentForm.php
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Entity\ContentEntityForm;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\user\PrivateTempStoreFactory;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Form controller for the group content edit forms.
- *
- * @ingroup group
- */
-class GroupContentForm extends ContentEntityForm {
-
-  /**
-   * The private store factory.
-   *
-   * @var \Drupal\user\PrivateTempStoreFactory
-   */
-  protected $privateTempStoreFactory;
-
-  /**
-   * Constructs a GroupContentForm object.
-   *
-   * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
-   *   The private store factory.
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   */
-  public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityManagerInterface $entity_manager) {
-    $this->privateTempStoreFactory = $temp_store_factory;
-    parent::__construct($entity_manager);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('user.private_tempstore'),
-      $container->get('entity.manager')
-    );
-  }
-
-  /**
-   * Returns the plugin responsible for this piece of group content.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerInterface
-   *   The responsible group content enabler plugin.
-   */
-  protected function getContentPlugin() {
-    /** @var \Drupal\group\Entity\GroupContent $group_content */
-    $group_content = $this->getEntity();
-    return $group_content->getContentPlugin();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function form(array $form, FormStateInterface $form_state) {
-    $form = parent::form($form, $form_state);
-
-    // Do not allow to edit the group content subject through the UI. Also hide
-    // the field when we are on step 2 of the creation wizard.
-    if ($this->operation !== 'add' || $form_state->has('store_id')) {
-      $form['entity_id']['#access'] = FALSE;
-    }
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function actions(array $form, FormStateInterface $form_state) {
-    $actions = parent::actions($form, $form_state);
-
-    // If we are on step 2 of the creation wizard, we need to alter the actions.
-    if ($form_state->has('store_id')) {
-      $store = $this->privateTempStoreFactory->get('group_content_wizard');
-      $store_id = $form_state->get('store_id');
-
-      // Add a back button to return to step 1 with.
-      $actions['back'] = [
-        '#type' => 'submit',
-        '#value' => $this->t('Back'),
-        '#submit' => ['::submitForm', '::back'],
-        '#limit_validation_errors' => [],
-      ];
-
-      // Make the label of the save button more intuitive.
-      $entity_type_id = $store->get("$store_id:entity")->getEntityTypeId();
-      $entity_type = $this->entityManager->getDefinition($entity_type_id);
-      $replace = [
-        '@entity_type' => strtolower($entity_type->getLabel()),
-        '@group' => $this->getEntity()->getGroup()->label(),
-      ];
-      $actions['submit']['#value'] = $this->t('Create @entity_type in @group', $replace);
-
-      // Make sure we complete the wizard before saving the group content.
-      $index = array_search('::save', $actions['submit']['#submit']);
-      array_splice($actions['submit']['#submit'], $index, 0, '::complete');
-    }
-
-    return $actions;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function save(array $form, FormStateInterface $form_state) {
-    $return = parent::save($form, $form_state);
-
-    /** @var \Drupal\group\Entity\GroupContentInterface $group_content */
-    $group_content = $this->getEntity();
-
-    // The below redirect ensures the user will be redirected to something they
-    // can view in the following order: The relationship entity (group content),
-    // they target entity itself, the group and finally the front page. This
-    // only applies if there was no destination GET parameter set in the URL.
-    if ($group_content->access('view')) {
-      $form_state->setRedirectUrl($group_content->toUrl());
-    }
-    elseif ($group_content->getEntity()->access('view')) {
-      $form_state->setRedirectUrl($group_content->getEntity()->toUrl());
-    }
-    elseif ($group_content->getGroup()->access('view')) {
-      $form_state->setRedirectUrl($group_content->getGroup()->toUrl());
-    }
-    else {
-      $form_state->setRedirect('<front>');
-    }
-
-    return $return;
-  }
-
-  /**
-   * Goes back to step 1 of the creation wizard.
-   *
-   * @param array $form
-   *   An associative array containing the structure of the form.
-   * @param \Drupal\Core\Form\FormStateInterface $form_state
-   *   The current state of the form.
-   *
-   * @see \Drupal\group\Entity\Controller\GroupContentController::createForm()
-   */
-  public function back(array &$form, FormStateInterface $form_state) {
-    $store = $this->privateTempStoreFactory->get('group_content_wizard');
-    $store_id = $form_state->get('store_id');
-    $store->set("$store_id:step", 1);
-
-    // Disable any URL-based redirect when going back to the previous step.
-    $request = $this->getRequest();
-    $form_state->setRedirect('<current>', [], ['query' => $request->query->all()]);
-    $request->query->remove('destination');
-  }
-
-  /**
-   * Completes the creation wizard by saving the target entity.
-   *
-   * Please note that we are instantiating an entity form to replicate the first
-   * step and call the save method on that form. This is done to ensure that any
-   * logic in the save handler is actually run when the wizard completes.
-   *
-   * @param array $form
-   *   An associative array containing the structure of the form.
-   * @param \Drupal\Core\Form\FormStateInterface $form_state
-   *   The current state of the form.
-   *
-   * @see \Drupal\group\Entity\Controller\GroupContentController::createForm()
-   */
-  public function complete(array &$form, FormStateInterface $form_state) {
-    $store = $this->privateTempStoreFactory->get('group_content_wizard');
-    $store_id = $form_state->get('store_id');
-    $entity = $store->get("$store_id:entity");
-
-    // Use the add form handler, if available, otherwise default.
-    $operation = 'default';
-    if ($entity->getEntityType()->getFormClass('add')) {
-      $operation = 'add';
-    }
-
-    // Replicate the form from step 1 and call the save method.
-    $form_object = $this->entityManager->getFormObject($entity->getEntityTypeId(), $operation);
-    $form_object->setEntity($entity);
-    $form_object->save($form, $form_state);
-
-    // Add the newly saved entity's ID to the group content entity.
-    $this->entity->set('entity_id', $entity->id());
-
-    // We also clear the temp store so we can start fresh next time around.
-    $store->delete("$store_id:step");
-    $store->delete("$store_id:entity");
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupContentTypeDeleteForm.php b/web/modules/group/src/Entity/Form/GroupContentTypeDeleteForm.php
deleted file mode 100644
index 381acf5f18..0000000000
--- a/web/modules/group/src/Entity/Form/GroupContentTypeDeleteForm.php
+++ /dev/null
@@ -1,125 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Entity\Query\QueryFactory;
-use Drupal\Core\Entity\EntityDeleteForm;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Url;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides a form for group content type deletion.
- *
- * Instead of just deleting the group content type here, we use this form as a
- * mean of uninstalling a group content enabler plugin which will actually
- * trigger the deletion of the group content type.
- */
-class GroupContentTypeDeleteForm extends EntityDeleteForm {
-
-  /**
-   * The query factory to create entity queries.
-   *
-   * @var \Drupal\Core\Entity\Query\QueryFactory
-   */
-  protected $queryFactory;
-
-  /**
-   * Constructs a new GroupContentTypeDeleteForm object.
-   *
-   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
-   *   The entity query object.
-   */
-  public function __construct(QueryFactory $query_factory) {
-    $this->queryFactory = $query_factory;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('entity.query')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getQuestion() {
-    /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-    $group_content_type = $this->getEntity();
-    return $this->t('Are you sure you want to uninstall the %plugin plugin?', ['%plugin' => $group_content_type->getContentPlugin()->getLabel()]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCancelUrl() {
-    /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-    $group_content_type = $this->getEntity();
-    return Url::fromRoute('entity.group_type.content_plugins', ['group_type' => $group_content_type->getGroupTypeId()]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDescription() {
-    /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-    $group_content_type = $this->getEntity();
-    $plugin = $group_content_type->getContentPlugin();
-    $replace = [
-      '%entity_type' => $this->entityTypeManager->getDefinition($plugin->getEntityTypeId())->getLabel(),
-      '%group_type' => $group_content_type->getGroupType()->label(),
-    ];
-    return $this->t('You will no longer be able to add %entity_type entities to %group_type groups.', $replace);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getConfirmText() {
-    return $this->t('Uninstall');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state) {
-    $entity_count = $this->queryFactory->get('group_content')
-      ->condition('type', $this->entity->id())
-      ->count()
-      ->execute();
-
-    if (!empty($entity_count)) {
-      $form['#title'] = $this->getQuestion();
-      $form['description'] = [
-        '#markup' => '<p>' . $this->t('You can not uninstall this content plugin until you have removed all of the content that uses it.') . '</p>'
-      ];
-
-      return $form;
-    }
-
-    return parent::buildForm($form, $form_state);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-    /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-    $group_content_type = $this->getEntity();
-    $group_type = $group_content_type->getGroupType();
-    $plugin = $group_content_type->getContentPlugin();
-
-    $group_content_type->delete();
-    \Drupal::logger('group_content_type')->notice('Uninstalled %plugin from %group_type.', [
-      '%plugin' => $plugin->getLabel(),
-      '%group_type' => $group_type->label(),
-    ]);
-
-    $form_state->setRedirect('entity.group_type.content_plugins', ['group_type' => $group_type->id()]);
-    drupal_set_message($this->t('The content plugin was uninstalled from the group type.'));
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupContentTypeForm.php b/web/modules/group/src/Entity/Form/GroupContentTypeForm.php
deleted file mode 100644
index 48b66cc154..0000000000
--- a/web/modules/group/src/Entity/Form/GroupContentTypeForm.php
+++ /dev/null
@@ -1,176 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Entity\EntityForm;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Form controller for group content type forms.
- */
-class GroupContentTypeForm extends EntityForm {
-
-  /**
-   * The group content enabler plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * Constructs a new GroupContentTypeForm.
-   *
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content plugin manager.
-   */
-  public function __construct(GroupContentEnablerManagerInterface $plugin_manager) {
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('plugin.manager.group_content_enabler')
-    );
-  }
-
-  /**
-   * Returns the configurable plugin for the group content type.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerInterface
-   *   The configurable group content enabler plugin.
-   */
-  protected function getContentPlugin() {
-    /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-    $group_content_type = $this->getEntity();
-    $group_type = $group_content_type->getGroupType();
-
-    // Initialize an empty plugin so we can show a default configuration form.
-    if ($this->operation == 'add') {
-      $plugin_id = $group_content_type->getContentPluginId();
-      $configuration['group_type_id'] = $group_type->id();
-      return $this->pluginManager->createInstance($plugin_id, $configuration);
-    }
-    // Return the already configured plugin for existing group content types.
-    else {
-      return $group_content_type->getContentPlugin();
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function form(array $form, FormStateInterface $form_state) {
-    /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-    $group_content_type = $this->getEntity();
-    $group_type = $group_content_type->getGroupType();
-    $plugin = $this->getContentPlugin();
-
-    // @todo These messages may need some love.
-    if ($this->operation == 'add') {
-      $form['#title'] = $this->t('Install content plugin');
-      $message = 'By installing the %plugin plugin, you will allow %entity_type entities to be added to groups of type %group_type';
-    }
-    else {
-      $form['#title'] = $this->t('Configure content plugin');
-      $message = 'This form allows you to configure the %plugin plugin for the %group_type group type.';
-    }
-
-    // Add in the replacements for the $message variable set above.
-    $replace = [
-      '%plugin' => $plugin->getLabel(),
-      '%entity_type' => $this->entityTypeManager->getDefinition($plugin->getEntityTypeId())->getLabel(),
-      '%group_type' => $group_type->label(),
-    ];
-
-    // Display a description to explain the purpose of the form.
-    $form['description'] = [
-      '#markup' => $this->t($message, $replace),
-    ];
-
-    // Add in the plugin configuration form.
-    $form += $plugin->buildConfigurationForm($form, $form_state);
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function actions(array $form, FormStateInterface $form_state) {
-    $actions['submit'] = array(
-      '#type' => 'submit',
-      '#value' => $this->operation == 'add' ? $this->t('Install plugin') : $this->t('Save configuration'),
-      '#submit' => array('::submitForm'),
-    );
-
-    return $actions;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validateForm(array &$form, FormStateInterface $form_state) {
-    $plugin = $this->getContentPlugin();
-    $plugin->validateConfigurationForm($form, $form_state);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-    /** @var \Drupal\group\Entity\GroupContentTypeInterface $group_content_type */
-    $group_content_type = $this->getEntity();
-    $group_type = $group_content_type->getGroupType();
-    $plugin = $this->getContentPlugin();
-    $plugin->submitConfigurationForm($form, $form_state);
-
-    // Remove button and internal Form API values from submitted values.
-    $form_state->cleanValues();
-
-    // Extract the values as configuration that should be saved.
-    $config = $form_state->getValues();
-
-    // If we are on an 'add' form, we create the group content type using the
-    // plugin configuration submitted using this form.
-    if ($this->operation == 'add') {
-      /** @var \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface $storage */
-      $storage = $this->entityTypeManager->getStorage('group_content_type');
-      $storage->createFromPlugin($group_type, $plugin->getPluginId(), $config)->save();
-      drupal_set_message($this->t('The content plugin was installed on the group type.'));
-    }
-    // Otherwise, we update the existing group content type's configuration.
-    else {
-      $group_content_type->updateContentPlugin($config);
-      drupal_set_message($this->t('The content plugin configuration was saved.'));
-    }
-
-    $form_state->setRedirect('entity.group_type.content_plugins', ['group_type' => $group_type->id()]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) {
-    if ($route_match->getRawParameter($entity_type_id) !== NULL) {
-      return $route_match->getParameter($entity_type_id);
-    }
-
-    // If we are on the create form, we can't extract an entity from the route,
-    // so we need to create one based on the route parameters.
-    $values = [];
-    if ($route_match->getRawParameter('group_type') !== NULL && $route_match->getRawParameter('plugin_id') !== NULL) {
-      $values = [
-        'group_type' => $route_match->getRawParameter('group_type'),
-        'content_plugin' => $route_match->getRawParameter('plugin_id'),
-      ];
-    }
-    return $this->entityTypeManager->getStorage($entity_type_id)->create($values);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupDeleteForm.php b/web/modules/group/src/Entity/Form/GroupDeleteForm.php
deleted file mode 100644
index 4b3286be36..0000000000
--- a/web/modules/group/src/Entity/Form/GroupDeleteForm.php
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Entity\ContentEntityConfirmFormBase;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Url;
-
-/**
- * Provides a form for deleting a group.
- */
-class GroupDeleteForm extends ContentEntityConfirmFormBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getQuestion() {
-    return $this->t('Are you sure you want to delete the group %name?', ['%name' => $this->entity->label()]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCancelURL() {
-    return new Url('entity.group.collection');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getConfirmText() {
-    return $this->t('Delete');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-    $entity = $this->getEntity();
-    $entity->delete();
-
-    \Drupal::logger('group')->notice('@type: deleted %title.', [
-      '@type' => $this->entity->bundle(),
-      '%title' => $this->entity->label(),
-    ]);
-    $form_state->setRedirect('entity.group.collection');
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupForm.php b/web/modules/group/src/Entity/Form/GroupForm.php
deleted file mode 100644
index 692a1101a6..0000000000
--- a/web/modules/group/src/Entity/Form/GroupForm.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Entity\ContentEntityForm;
-use Drupal\Core\Form\FormStateInterface;
-
-/**
- * Form controller for the group edit forms.
- *
- * @ingroup group
- */
-class GroupForm extends ContentEntityForm {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function save(array $form, FormStateInterface $form_state) {
-    // We call the parent function first so the entity is saved. We can then
-    // read out its ID and redirect to the canonical route.
-    $return = parent::save($form, $form_state);
-
-    // Display success message.
-    $t_args = [
-      '@type' => $this->entity->getGroupType()->label(),
-      '%title' => $this->entity->label(),
-    ];
-    drupal_set_message(t('@type %title has been created.', $t_args));
-
-    $form_state->setRedirect('entity.group.canonical', ['group' => $this->entity->id()]);
-    return $return;
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupRoleDeleteForm.php b/web/modules/group/src/Entity/Form/GroupRoleDeleteForm.php
deleted file mode 100644
index cc5f6d953f..0000000000
--- a/web/modules/group/src/Entity/Form/GroupRoleDeleteForm.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Entity\EntityDeleteForm;
-use Drupal\Core\Form\FormStateInterface;
-
-/**
- * Provides a form for group role deletion.
- */
-class GroupRoleDeleteForm extends EntityDeleteForm {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state) {
-    if ($this->entity->isInternal()) {
-      return [
-        '#title' => t('Error'),
-        'description' => [
-          '#prefix' => '<p>',
-          '#suffix' => '</p>',
-          '#markup' => t('Cannot edit an internal group role directly.'),
-        ],
-      ];
-    }
-
-    return parent::buildForm($form, $form_state);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupRoleForm.php b/web/modules/group/src/Entity/Form/GroupRoleForm.php
deleted file mode 100644
index bfd6d0f276..0000000000
--- a/web/modules/group/src/Entity/Form/GroupRoleForm.php
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Entity\EntityForm;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\group\Entity\GroupRole;
-
-/**
- * Form controller for group role forms.
- */
-class GroupRoleForm extends EntityForm {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state) {
-    /** @var \Drupal\group\Entity\GroupRoleInterface $group_role */
-    $group_role = $this->entity;
-    if ($group_role->isInternal()) {
-      return [
-        '#title' => t('Error'),
-        'description' => [
-          '#prefix' => '<p>',
-          '#suffix' => '</p>',
-          '#markup' => t('Cannot edit an internal group role directly.'),
-        ],
-      ];
-    }
-
-    return parent::buildForm($form, $form_state);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function form(array $form, FormStateInterface $form_state) {
-    $form = parent::form($form, $form_state);
-
-    /** @var \Drupal\group\Entity\GroupRoleInterface $group_role */
-    $group_role = $this->entity;
-    $group_role_id = '';
-
-    $form['label'] = [
-      '#title' => t('Name'),
-      '#type' => 'textfield',
-      '#default_value' => $group_role->label(),
-      '#description' => t('The human-readable name of this group role. This text will be displayed on the group permissions page.'),
-      '#required' => TRUE,
-      '#size' => 30,
-    ];
-
-    // Since group role IDs are prefixed by the group type's ID followed by a
-    // period, we need to save some space for that.
-    $subtract = strlen($group_role->getGroupTypeId()) + 1;
-
-    // Since machine names with periods in it are technically not allowed, we
-    // strip the group type ID prefix when editing a group role.
-    if ($group_role->id()) {
-      list(, $group_role_id) = explode('-', $group_role->id(), 2);
-    }
-
-    $form['id'] = [
-      '#type' => 'machine_name',
-      '#default_value' => $group_role_id,
-      '#maxlength' => EntityTypeInterface::ID_MAX_LENGTH - $subtract,
-      '#machine_name' => [
-        'exists' => [$this, 'exists'],
-        'source' => ['label'],
-      ],
-      '#description' => t('A unique machine-readable name for this group role. It must only contain lowercase letters, numbers, and underscores.'),
-      '#disabled' => !$group_role->isNew(),
-      '#field_prefix' => $group_role->getGroupTypeId() . '-',
-    ];
-
-    $form['weight'] = [
-      '#type' => 'value',
-      '#value' => $group_role->getWeight(),
-    ];
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function actions(array $form, FormStateInterface $form_state) {
-    $actions = parent::actions($form, $form_state);
-    $actions['submit']['#value'] = t('Save group role');
-    $actions['delete']['#value'] = t('Delete group role');
-    return $actions;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validateForm(array &$form, FormStateInterface $form_state) {
-    parent::validateForm($form, $form_state);
-
-    $id = trim($form_state->getValue('id'));
-    // '0' is invalid, since elsewhere we might check it using empty().
-    if ($id == '0') {
-      $form_state->setErrorByName('id', $this->t("Invalid machine-readable name. Enter a name other than %invalid.", ['%invalid' => $id]));
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function save(array $form, FormStateInterface $form_state) {
-    /** @var \Drupal\group\Entity\GroupRoleInterface $group_role */
-    $group_role = $this->entity;
-    $group_role->set('id', $group_role->getGroupTypeId() . '-' . $group_role->id());
-    $group_role->set('label', trim($group_role->label()));
-
-    $status = $group_role->save();
-    $t_args = ['%label' => $group_role->label()];
-
-    if ($status == SAVED_UPDATED) {
-      drupal_set_message(t('The group role %label has been updated.', $t_args));
-    }
-    elseif ($status == SAVED_NEW) {
-      drupal_set_message(t('The group role %label has been added.', $t_args));
-
-      $context = array_merge($t_args, ['link' => $group_role->toLink($this->t('View'), 'collection')->toString()]);
-      $this->logger('group')->notice('Added group role %label.', $context);
-    }
-
-    $form_state->setRedirectUrl($group_role->toUrl('collection'));
-  }
-
-  /**
-   * Checks whether a group role ID exists already.
-   *
-   * @param string $id
-   *
-   * @return bool
-   *   Whether the ID is taken.
-   */
-  public function exists($id) {
-    /** @var \Drupal\group\Entity\GroupRoleInterface $group_role */
-    $group_role = $this->entity;
-    return (boolean) GroupRole::load($group_role->getGroupTypeId() . '-' .$id);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) {
-    if ($route_match->getRawParameter($entity_type_id) !== NULL) {
-      return $route_match->getParameter($entity_type_id);
-    }
-
-    // If we are on the create form, we can't extract an entity from the route,
-    // so we need to create one based on the route parameters.
-    $values = [];
-    if ($route_match->getRawParameter('group_type') !== NULL) {
-      $values['group_type'] = $route_match->getRawParameter('group_type');
-    }
-    return $this->entityTypeManager->getStorage($entity_type_id)->create($values);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupTypeDeleteForm.php b/web/modules/group/src/Entity/Form/GroupTypeDeleteForm.php
deleted file mode 100644
index 55798c8dd4..0000000000
--- a/web/modules/group/src/Entity/Form/GroupTypeDeleteForm.php
+++ /dev/null
@@ -1,67 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Entity\Query\QueryFactory;
-use Drupal\Core\Entity\EntityDeleteForm;
-use Drupal\Core\Form\FormStateInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides a form for group type deletion.
- */
-class GroupTypeDeleteForm extends EntityDeleteForm {
-
-  /**
-   * The query factory to create entity queries.
-   *
-   * @var \Drupal\Core\Entity\Query\QueryFactory
-   */
-  protected $queryFactory;
-
-  /**
-   * Constructs a new GroupTypeDeleteForm object.
-   *
-   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
-   *   The entity query object.
-   */
-  public function __construct(QueryFactory $query_factory) {
-    $this->queryFactory = $query_factory;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('entity.query')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state) {
-    $num_groups = $this->queryFactory->get('group')
-      ->condition('type', $this->entity->id())
-      ->count()
-      ->execute();
-
-    if (!empty($num_groups)) {
-      $common = ' You can not remove this group type until you have removed all of the %type groups.';
-      $single = '%type is used by 1 group on your site.' . $common;
-      $multiple = '%type is used by @count groups on your site.' . $common;
-      $replace = ['%type' => $this->entity->label()];
-
-      $form['#title'] = $this->getQuestion();
-      $form['description'] = [
-        '#markup' => '<p>' . $this->formatPlural($num_groups, $single, $multiple, $replace) . '</p>'
-      ];
-
-      return $form;
-    }
-
-    return parent::buildForm($form, $form_state);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Form/GroupTypeForm.php b/web/modules/group/src/Entity/Form/GroupTypeForm.php
deleted file mode 100644
index 0440f8c4a4..0000000000
--- a/web/modules/group/src/Entity/Form/GroupTypeForm.php
+++ /dev/null
@@ -1,171 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Form;
-
-use Drupal\Core\Url;
-use Drupal\group\Entity\GroupTypeInterface;
-use Drupal\Core\Entity\BundleEntityFormBase;
-use Drupal\Core\Form\FormStateInterface;
-
-/**
- * Form controller for group type forms.
- */
-class GroupTypeForm extends BundleEntityFormBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function form(array $form, FormStateInterface $form_state) {
-    /** @var \Drupal\group\Entity\GroupTypeInterface $type */
-    $form = parent::form($form, $form_state);
-    $type = $this->entity;
-
-    $form['label'] = [
-      '#title' => $this->t('Name'),
-      '#type' => 'textfield',
-      '#default_value' => $type->label(),
-      '#description' => $this->t('The human-readable name of this group type. This text will be displayed as part of the list on the %group-add page. This name must be unique.', [
-        '%group-add' => $this->t('Add group'),
-      ]),
-      '#required' => TRUE,
-      '#size' => 30,
-    ];
-
-    $form['id'] = [
-      '#type' => 'machine_name',
-      '#default_value' => $type->id(),
-      '#maxlength' => GroupTypeInterface::ID_MAX_LENGTH,
-      '#machine_name' => [
-        'exists' => ['Drupal\group\Entity\GroupType', 'load'],
-        'source' => ['label'],
-      ],
-      '#description' => $this->t('A unique machine-readable name for this group type. It must only contain lowercase letters, numbers, and underscores. This name will be used for constructing the URL of the %group-add page, in which underscores will be converted into hyphens.', [
-        '%group-add' => $this->t('Add group'),
-      ]),
-    ];
-
-    $form['description'] = [
-      '#title' => $this->t('Description'),
-      '#type' => 'textarea',
-      '#default_value' => $type->getDescription(),
-      '#description' => $this->t('This text will be displayed on the <em>Add group</em> page.'),
-    ];
-
-    // Add-form specific elements.
-    if ($this->operation == 'add') {
-      $form['add_admin_role'] = [
-        '#title' => $this->t('Automatically configure an administrative role'),
-        '#type' => 'checkbox',
-        '#default_value' => 0,
-        '#description' => $this->t("This will create an 'Admin' role by default which will have all currently defined permissions."),
-      ];
-
-      $form['assign_admin_role'] = [
-        '#title' => $this->t('Automatically assign this administrative role to group creators'),
-        '#type' => 'checkbox',
-        '#default_value' => 0,
-        '#description' => $this->t("This will assign the 'Admin' role to anyone who creates a group of this type."),
-        '#states' => [
-          'visible' => [':input[name="add_admin_role"]' => ['checked' => TRUE]],
-        ],
-      ];
-    }
-    // Edit-form specific elements.
-    else {
-      $options = [];
-      foreach ($type->getRoles(FALSE) as $group_role) {
-        $options[$group_role->id()] = $group_role->label();
-      }
-
-      $form['creator_roles'] = [
-        '#title' => $this->t('Group creator roles'),
-        '#type' => 'checkboxes',
-        '#options' => $options,
-        '#default_value' => $type->getCreatorRoleIds(),
-        '#description' => $this->t('Please select which custom group roles a group creator will receive.'),
-      ];
-
-      if (empty($options)) {
-        $add_role_url = Url::fromRoute('entity.group_role.add_form', ['group_type' => $type->id()]);
-        $t_args = ['@url' => $add_role_url->toString()];
-        $description = $this->t('You do not have any custom group roles yet, <a href="@url">create one here</a>.', $t_args);
-        $form['creator_roles']['#description'] .= "<br /><em>$description</em>";
-      }
-    }
-
-    return $this->protectBundleIdElement($form);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function actions(array $form, FormStateInterface $form_state) {
-    $actions = parent::actions($form, $form_state);
-    $actions['submit']['#value'] = $this->t('Save group type');
-    $actions['delete']['#value'] = $this->t('Delete group type');
-    return $actions;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validateForm(array &$form, FormStateInterface $form_state) {
-    parent::validateForm($form, $form_state);
-
-    $id = trim($form_state->getValue('id'));
-    // '0' is invalid, since elsewhere we might check it using empty().
-    if ($id == '0') {
-      $form_state->setErrorByName('id', $this->t("Invalid machine-readable name. Enter a name other than %invalid.", ['%invalid' => $id]));
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function save(array $form, FormStateInterface $form_state) {
-    /** @var \Drupal\group\Entity\GroupTypeInterface $type */
-    $type = $this->entity;
-
-    // Trim any whitespace off the label.
-    $type->set('label', trim($type->label()));
-
-    // Clean up the creator role IDs as it comes from a checkboxes element.
-    if ($creator_roles = $type->getCreatorRoleIds()) {
-      $type->set('creator_roles', array_values(array_filter($creator_roles)));
-    }
-
-    $status = $type->save();
-    $t_args = ['%label' => $type->label()];
-
-    if ($status == SAVED_UPDATED) {
-      drupal_set_message($this->t('The group type %label has been updated.', $t_args));
-    }
-    elseif ($status == SAVED_NEW) {
-      drupal_set_message($this->t('The group type %label has been added. You may now configure which roles a group creator will receive by editing the group type.', $t_args));
-      $context = array_merge($t_args, ['link' => $type->toLink($this->t('View'), 'collection')->toString()]);
-      $this->logger('group')->notice('Added group type %label.', $context);
-
-      // Optionally create a default admin role.
-      if ($form_state->getValue('add_admin_role')) {
-        $storage = $this->entityTypeManager->getStorage('group_role');
-
-        /** @var \Drupal\group\Entity\GroupRoleInterface $group_role */
-        $group_role = $storage->create([
-          'id' => $type->id() . '-admin',
-          'label' => $this->t('Admin'),
-          'weight' => 100,
-          'group_type' => $type->id(),
-        ]);
-        $group_role->grantAllPermissions()->save();
-
-        // Optionally auto-assign the admin role to group creators.
-        if ($form_state->getValue('assign_admin_role')) {
-          $type->set('creator_roles', [$type->id() . '-admin'])->save();
-        }
-      }
-    }
-
-    $form_state->setRedirectUrl($type->toUrl('collection'));
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Group.php b/web/modules/group/src/Entity/Group.php
deleted file mode 100644
index 6d90179ca4..0000000000
--- a/web/modules/group/src/Entity/Group.php
+++ /dev/null
@@ -1,361 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\Core\Field\BaseFieldDefinition;
-use Drupal\Core\Entity\ContentEntityBase;
-use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\EntityChangedTrait;
-use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\user\UserInterface;
-
-/**
- * Defines the Group entity.
- *
- * @ingroup group
- *
- * @ContentEntityType(
- *   id = "group",
- *   label = @Translation("Group"),
- *   label_singular = @Translation("group"),
- *   label_plural = @Translation("groups"),
- *   label_count = @PluralTranslation(
- *     singular = "@count group",
- *     plural = "@count groups"
- *   ),
- *   bundle_label = @Translation("Group type"),
- *   handlers = {
- *     "view_builder" = "Drupal\group\Entity\ViewBuilder\GroupViewBuilder",
- *     "views_data" = "Drupal\group\Entity\Views\GroupViewsData",
- *     "list_builder" = "Drupal\group\Entity\Controller\GroupListBuilder",
- *     "route_provider" = {
- *       "html" = "Drupal\group\Entity\Routing\GroupRouteProvider",
- *     },
- *     "form" = {
- *       "add" = "Drupal\group\Entity\Form\GroupForm",
- *       "edit" = "Drupal\group\Entity\Form\GroupForm",
- *       "delete" = "Drupal\group\Entity\Form\GroupDeleteForm",
- *     },
- *     "access" = "Drupal\group\Entity\Access\GroupAccessControlHandler",
- *   },
- *   admin_permission = "administer group",
- *   base_table = "groups",
- *   data_table = "groups_field_data",
- *   translatable = TRUE,
- *   entity_keys = {
- *     "id" = "id",
- *     "uuid" = "uuid",
- *     "langcode" = "langcode",
- *     "bundle" = "type",
- *     "label" = "label"
- *   },
- *   links = {
- *     "add-form" = "/group/add/{group_type}",
- *     "add-page" = "/group/add",
- *     "canonical" = "/group/{group}",
- *     "collection" = "/admin/group",
- *     "edit-form" = "/group/{group}/edit",
- *     "delete-form" = "/group/{group}/delete"
- *   },
- *   bundle_entity_type = "group_type",
- *   field_ui_base_route = "entity.group_type.edit_form",
- *   permission_granularity = "bundle"
- * )
- */
-class Group extends ContentEntityBase implements GroupInterface {
-
-  use EntityChangedTrait;
-
-  /**
-   * Gets the group membership loader.
-   *
-   * @return \Drupal\group\GroupMembershipLoaderInterface
-   */
-  protected function membershipLoader() {
-    return \Drupal::service('group.membership_loader');
-  }
-
-  /**
-   * Gets the group content storage.
-   *
-   * @return \Drupal\group\Entity\Storage\GroupContentStorageInterface
-   */
-  protected function groupContentStorage() {
-    return $this->entityTypeManager()->getStorage('group_content');
-  }
-
-  /**
-   * Gets the group role storage.
-   *
-   * @return \Drupal\group\Entity\Storage\GroupRoleStorageInterface
-   */
-  protected function groupRoleStorage() {
-    return $this->entityTypeManager()->getStorage('group_role');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCreatedTime() {
-    return $this->get('created')->value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getOwner() {
-    return $this->get('uid')->entity;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getOwnerId() {
-    return $this->get('uid')->target_id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setOwnerId($uid) {
-    $this->set('uid', $uid);
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setOwner(UserInterface $account) {
-    $this->set('uid', $account->id());
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupType() {
-    return $this->type->entity;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function addContent(ContentEntityInterface $entity, $plugin_id, $values = []) {
-    $plugin = $this->getGroupType()->getContentPlugin($plugin_id);
-
-    // Only add the entity if the provided plugin supports it.
-    // @todo Verify bundle as well and throw exceptions?
-    if ($entity->getEntityTypeId() == $plugin->getEntityTypeId()) {
-      $keys = [
-        'type' => $plugin->getContentTypeConfigId(),
-        'gid' => $this->id(),
-        'entity_id' => $entity->id(),
-      ];
-      GroupContent::create($keys + $values)->save();
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContent($plugin_id = NULL, $filters = []) {
-    return $this->groupContentStorage()->loadByGroup($this, $plugin_id, $filters);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentByEntityId($plugin_id, $id) {
-    return $this->getContent($plugin_id, ['entity_id' => $id]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentEntities($plugin_id = NULL, $filters = []) {
-    $entities = [];
-
-    foreach ($this->getContent($plugin_id, $filters) as $group_content) {
-      $entities[] = $group_content->getEntity();
-    }
-
-    return $entities;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function addMember(UserInterface $account, $values = []) {
-    if (!$this->getMember($account)) {
-      $this->addContent($account, 'group_membership', $values);
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function removeMember(UserInterface $account) {
-    if ($member = $this->getMember($account)) {
-      $member->getGroupContent()->delete();
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getMember(AccountInterface $account) {
-    return $this->membershipLoader()->load($this, $account);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getMembers($roles = NULL) {
-    return $this->membershipLoader()->loadByGroup($this, $roles);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function hasPermission($permission, AccountInterface $account) {
-    // If the account can bypass all group access, return immediately.
-    if ($account->hasPermission('bypass group access')) {
-      return TRUE;
-    }
-
-    // Before anything else, check if the user can administer the group.
-    if ($permission != 'administer group' && $this->hasPermission('administer group', $account)) {
-      return TRUE;
-    }
-
-    // Retrieve all of the group roles the user may get for the group.
-    $group_roles = $this->groupRoleStorage()->loadByUserAndGroup($account, $this);
-
-    // Check each retrieved role for the requested permission.
-    foreach ($group_roles as $group_role) {
-      if ($group_role->hasPermission($permission)) {
-        return TRUE;
-      }
-    }
-
-    // If no role had the requested permission, we deny access.
-    return FALSE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
-    $fields = parent::baseFieldDefinitions($entity_type);
-
-    $fields['label'] = BaseFieldDefinition::create('string')
-      ->setLabel(t('Title'))
-      ->setRequired(TRUE)
-      ->setTranslatable(TRUE)
-      ->setSetting('max_length', 255)
-      ->setDisplayOptions('view', [
-        'label' => 'hidden',
-        'type' => 'string',
-        'weight' => -5,
-      ])
-      ->setDisplayOptions('form', [
-        'type' => 'string_textfield',
-        'weight' => -5,
-      ])
-      ->setDisplayConfigurable('view', TRUE)
-      ->setDisplayConfigurable('form', TRUE);
-
-    $fields['uid'] = BaseFieldDefinition::create('entity_reference')
-      ->setLabel(t('Group creator'))
-      ->setDescription(t('The username of the group creator.'))
-      ->setSetting('target_type', 'user')
-      ->setSetting('handler', 'default')
-      ->setDefaultValueCallback('Drupal\group\Entity\Group::getCurrentUserId')
-      ->setTranslatable(TRUE)
-      ->setDisplayConfigurable('view', TRUE)
-      ->setDisplayConfigurable('form', TRUE);
-
-    $fields['created'] = BaseFieldDefinition::create('created')
-      ->setLabel(t('Created on'))
-      ->setDescription(t('The time that the group was created.'))
-      ->setTranslatable(TRUE)
-      ->setDisplayOptions('view', array(
-        'label' => 'hidden',
-        'type' => 'hidden',
-        'weight' => 0,
-      ))
-      ->setDisplayConfigurable('view', TRUE);
-
-    $fields['changed'] = BaseFieldDefinition::create('changed')
-      ->setLabel(t('Changed on'))
-      ->setDescription(t('The time that the group was last edited.'))
-      ->setTranslatable(TRUE)
-      ->setDisplayOptions('view', array(
-        'label' => 'hidden',
-        'type' => 'hidden',
-        'weight' => 0,
-      ))
-      ->setDisplayConfigurable('view', TRUE);
-
-    if (\Drupal::moduleHandler()->moduleExists('path')) {
-      $fields['path'] = BaseFieldDefinition::create('path')
-        ->setLabel(t('URL alias'))
-        ->setTranslatable(TRUE)
-        ->setDisplayOptions('form', array(
-          'type' => 'path',
-          'weight' => 30,
-        ))
-        ->setDisplayConfigurable('form', TRUE)
-        ->setComputed(TRUE);
-    }
-
-    return $fields;
-  }
-
-  /**
-   * Default value callback for 'uid' base field definition.
-   *
-   * @see ::baseFieldDefinitions()
-   *
-   * @return array
-   *   An array of default values.
-   */
-  public static function getCurrentUserId() {
-    return [\Drupal::currentUser()->id()];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
-    parent::postSave($storage, $update);
-
-    // If a new group is created, add the creator as a member by default.
-    if ($update === FALSE) {
-      $values = ['group_roles' => $this->getGroupType()->getCreatorRoleIds()];
-      $this->addMember($this->getOwner(), $values);
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function preDelete(EntityStorageInterface $storage, array $entities) {
-    // Remove all group content from these groups as well.
-    foreach ($entities as $group) {
-      foreach ($group->getContent() as $group_content) {
-        $group_content->delete();
-      }
-    }
-  }
-
-}
diff --git a/web/modules/group/src/Entity/GroupContent.php b/web/modules/group/src/Entity/GroupContent.php
deleted file mode 100644
index 38728449ed..0000000000
--- a/web/modules/group/src/Entity/GroupContent.php
+++ /dev/null
@@ -1,370 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\user\UserInterface;
-use Drupal\Core\Field\BaseFieldDefinition;
-use Drupal\Core\Entity\ContentEntityBase;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\EntityChangedTrait;
-use Drupal\Core\Entity\EntityStorageInterface;
-
-/**
- * Defines the Group content entity.
- *
- * @ingroup group
- *
- * @ContentEntityType(
- *   id = "group_content",
- *   label = @Translation("Group content"),
- *   label_singular = @Translation("group content item"),
- *   label_plural = @Translation("group content items"),
- *   label_count = @PluralTranslation(
- *     singular = "@count group content item",
- *     plural = "@count group content items"
- *   ),
- *   bundle_label = @Translation("Group content type"),
- *   handlers = {
- *     "storage" = "Drupal\group\Entity\Storage\GroupContentStorage",
- *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
- *     "views_data" = "Drupal\group\Entity\Views\GroupContentViewsData",
- *     "list_builder" = "Drupal\group\Entity\Controller\GroupContentListBuilder",
- *     "route_provider" = {
- *       "html" = "Drupal\group\Entity\Routing\GroupContentRouteProvider",
- *     },
- *     "form" = {
- *       "add" = "Drupal\group\Entity\Form\GroupContentForm",
- *       "edit" = "Drupal\group\Entity\Form\GroupContentForm",
- *       "delete" = "Drupal\group\Entity\Form\GroupContentDeleteForm",
- *       "group-join" = "Drupal\group\Form\GroupJoinForm",
- *       "group-leave" = "Drupal\group\Form\GroupLeaveForm",
- *     },
- *     "access" = "Drupal\group\Entity\Access\GroupContentAccessControlHandler",
- *   },
- *   base_table = "group_content",
- *   data_table = "group_content_field_data",
- *   translatable = TRUE,
- *   entity_keys = {
- *     "id" = "id",
- *     "uuid" = "uuid",
- *     "langcode" = "langcode",
- *     "bundle" = "type",
- *     "label" = "label"
- *   },
- *   links = {
- *     "add-form" = "/group/{group}/content/add/{plugin_id}",
- *     "add-page" = "/group/{group}/content/add",
- *     "canonical" = "/group/{group}/content/{group_content}",
- *     "collection" = "/group/{group}/content",
- *     "create-form" = "/group/{group}/content/create/{plugin_id}",
- *     "create-page" = "/group/{group}/content/create",
- *     "delete-form" = "/group/{group}/content/{group_content}/delete",
- *     "edit-form" = "/group/{group}/content/{group_content}/edit"
- *   },
- *   bundle_entity_type = "group_content_type",
- *   field_ui_base_route = "entity.group_content_type.edit_form",
- *   permission_granularity = "bundle",
- *   constraints = {
- *     "GroupContentCardinality" = {}
- *   }
- * )
- */
-class GroupContent extends ContentEntityBase implements GroupContentInterface {
-
-  use EntityChangedTrait;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupContentType() {
-    return $this->type->entity;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroup() {
-    return $this->gid->entity;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntity() {
-    return $this->entity_id->entity;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentPlugin() {
-    return $this->getGroupContentType()->getContentPlugin();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function loadByContentPluginId($plugin_id) {
-    $group_content_types = GroupContentType::loadByContentPluginId($plugin_id);
-
-    if (empty($group_content_types)) {
-      return [];
-    }
-
-    return \Drupal::entityTypeManager()
-      ->getStorage('group_content')
-      ->loadByProperties(['type' => array_keys($group_content_types)]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function loadByEntity(ContentEntityInterface $entity) {
-    $group_content_types = GroupContentType::loadByEntityTypeId($entity->getEntityTypeId());
-
-    // If no responsible group content types were found, we return nothing.
-    if (empty($group_content_types)) {
-      return [];
-    }
-
-    return \Drupal::entityTypeManager()
-      ->getStorage('group_content')
-      ->loadByProperties([
-        'type' => array_keys($group_content_types),
-        'entity_id' => $entity->id(),
-      ]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function label() {
-    return $this->getContentPlugin()->getContentLabel($this);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function urlRouteParameters($rel) {
-    $uri_route_parameters = parent::urlRouteParameters($rel);
-    $uri_route_parameters['group'] = $this->getGroup()->id();
-    return $uri_route_parameters;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCreatedTime() {
-    return $this->get('created')->value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getChangedTime() {
-    return $this->get('changed')->value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getOwner() {
-    return $this->get('uid')->entity;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getOwnerId() {
-    return $this->get('uid')->target_id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setOwnerId($uid) {
-    $this->set('uid', $uid);
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setOwner(UserInterface $account) {
-    $this->set('uid', $account->id());
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function preSave(EntityStorageInterface $storage) {
-    parent::preSave($storage);
-
-    // Set the label so the DB also reflects it.
-    $this->set('label', $this->label());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
-    parent::postSave($storage, $update);
-
-    if ($update === FALSE) {
-      // We want to make sure that the entity we just added to the group behaves
-      // as a grouped entity. This means we may need to update access records,
-      // flush some caches containing the entity or perform other operations we
-      // cannot possibly know about. Lucky for us, all of that behavior usually
-      // happens when saving an entity so let's re-save the added entity.
-      $this->getEntity()->save();
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function postDelete(EntityStorageInterface $storage, array $entities) {
-    parent::postDelete($storage, $entities);
-
-    // For the same reasons we re-save entities that are added to a group, we
-    // need to re-save entities that were removed from one. See ::postSave().
-    /** @var GroupContentInterface[] $entities */
-    foreach ($entities as $group_content) {
-      // We only save the entity if it still exists to avoid trying to save an
-      // entity that just got deleted and triggered the deletion of its group
-      // content entities.
-      if ($entity = $group_content->getEntity()) {
-        // @todo Revisit when https://www.drupal.org/node/2754399 lands.
-        $entity->save();
-      }
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
-    $fields = parent::baseFieldDefinitions($entity_type);
-
-    $fields['gid'] = BaseFieldDefinition::create('entity_reference')
-      ->setLabel(t('Parent group'))
-      ->setDescription(t('The group containing the entity.'))
-      ->setSetting('target_type', 'group')
-      ->setReadOnly(TRUE);
-
-    // Borrowed this logic from the Comment module.
-    // Warning! May change in the future: https://www.drupal.org/node/2346347
-    $fields['entity_id'] = BaseFieldDefinition::create('entity_reference')
-      ->setLabel(t('Content'))
-      ->setDescription(t('The entity to add to the group.'))
-      ->setDisplayOptions('form', [
-        'type' => 'entity_reference_autocomplete',
-        'weight' => 5,
-        'settings' => [
-          'match_operator' => 'CONTAINS',
-          'size' => '60',
-          'placeholder' => '',
-        ],
-      ])
-      ->setDisplayConfigurable('view', TRUE)
-      ->setDisplayConfigurable('form', TRUE)
-      ->setRequired(TRUE);
-
-    $fields['label'] = BaseFieldDefinition::create('string')
-      ->setLabel(t('Title'))
-      ->setReadOnly(TRUE)
-      ->setTranslatable(TRUE)
-      ->setSetting('max_length', 255)
-      ->setDisplayOptions('view', [
-        'label' => 'hidden',
-        'type' => 'string',
-        'weight' => -5,
-      ]);
-
-    $fields['uid'] = BaseFieldDefinition::create('entity_reference')
-      ->setLabel(t('Group content creator'))
-      ->setDescription(t('The username of the group content creator.'))
-      ->setSetting('target_type', 'user')
-      ->setSetting('handler', 'default')
-      ->setDefaultValueCallback('Drupal\group\Entity\GroupContent::getCurrentUserId')
-      ->setTranslatable(TRUE)
-      ->setDisplayConfigurable('view', TRUE)
-      ->setDisplayConfigurable('form', TRUE);
-
-    $fields['created'] = BaseFieldDefinition::create('created')
-      ->setLabel(t('Created on'))
-      ->setDescription(t('The time that the group content was created.'))
-      ->setTranslatable(TRUE);
-
-    $fields['changed'] = BaseFieldDefinition::create('changed')
-      ->setLabel(t('Changed on'))
-      ->setDescription(t('The time that the group content was last edited.'))
-      ->setTranslatable(TRUE);
-
-    if (\Drupal::moduleHandler()->moduleExists('path')) {
-      $fields['path'] = BaseFieldDefinition::create('path')
-        ->setLabel(t('URL alias'))
-        ->setTranslatable(TRUE)
-        ->setDisplayOptions('form', array(
-          'type' => 'path',
-          'weight' => 30,
-        ))
-        ->setDisplayConfigurable('form', TRUE)
-        ->setComputed(TRUE);
-    }
-
-    return $fields;
-  }
-
-  /**
-   * Default value callback for 'uid' base field definition.
-   *
-   * @see ::baseFieldDefinitions()
-   *
-   * @return array
-   *   An array of default values.
-   */
-  public static function getCurrentUserId() {
-    return [\Drupal::currentUser()->id()];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
-    // Borrowed this logic from the Comment module.
-    // Warning! May change in the future: https://www.drupal.org/node/2346347
-    if ($group_content_type = GroupContentType::load($bundle)) {
-      $plugin = $group_content_type->getContentPlugin();
-
-      /** @var \Drupal\Core\Field\BaseFieldDefinition $original */
-      $original = $base_field_definitions['entity_id'];
-
-      // Recreated the original entity_id field so that it does not contain any
-      // data in its "propertyDefinitions" or "schema" properties because those
-      // were set based on the base field which had no clue what bundle to serve
-      // up until now. This is a bug in core because we can't simply unset those
-      // two properties, see: https://www.drupal.org/node/2346329
-      $fields['entity_id'] = BaseFieldDefinition::create('entity_reference')
-        ->setLabel($plugin->getEntityReferenceLabel() ?: $original->getLabel())
-        ->setDescription($plugin->getEntityReferenceDescription() ?: $original->getDescription())
-        ->setConstraints($original->getConstraints())
-        ->setDisplayOptions('view', $original->getDisplayOptions('view'))
-        ->setDisplayOptions('form', $original->getDisplayOptions('form'))
-        ->setDisplayConfigurable('view', $original->isDisplayConfigurable('view'))
-        ->setDisplayConfigurable('form', $original->isDisplayConfigurable('form'))
-        ->setRequired($original->isRequired());
-
-      foreach ($plugin->getEntityReferenceSettings() as $name => $setting) {
-        $fields['entity_id']->setSetting($name, $setting);
-      }
-
-      return $fields;
-    }
-
-    return [];
-  }
-
-}
diff --git a/web/modules/group/src/Entity/GroupContentInterface.php b/web/modules/group/src/Entity/GroupContentInterface.php
deleted file mode 100644
index 28965aa114..0000000000
--- a/web/modules/group/src/Entity/GroupContentInterface.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\user\EntityOwnerInterface;
-use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\EntityChangedInterface;
-
-/**
- * Provides an interface defining a Group content entity.
- *
- * @ingroup group
- */
-interface GroupContentInterface extends ContentEntityInterface, EntityOwnerInterface, EntityChangedInterface {
-
-  /**
-   * Returns the group content type entity the group content uses.
-   *
-   * @return \Drupal\group\Entity\GroupContentTypeInterface
-   */
-  public function getGroupContentType();
-
-  /**
-   * Returns the group the group content belongs to.
-   *
-   * @return \Drupal\group\Entity\GroupInterface
-   */
-  public function getGroup();
-
-  /**
-   * Returns the entity that was added as group content.
-   *
-   * @return \Drupal\Core\Entity\EntityInterface
-   */
-  public function getEntity();
-
-  /**
-   * Returns the content enabler plugin that handles the group content.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerInterface
-   */
-  public function getContentPlugin();
-
-  /**
-   * Loads group content entities by their responsible plugin ID.
-   *
-   * @param string $plugin_id
-   *   The ID of the content enabler plugin.
-   *
-   * @return \Drupal\group\Entity\GroupContentInterface[]
-   *   An array of group content entities indexed by their IDs.
-   */
-  public static function loadByContentPluginId($plugin_id);
-
-  /**
-   * Loads group content entities which reference a given entity.
-   *
-   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
-   *   An entity which may be within one or more groups.
-   *
-   * @return \Drupal\group\Entity\GroupContentInterface[]
-   *   An array of group content entities which reference the given entity.
-   */
-  public static function loadByEntity(ContentEntityInterface $entity);
-
-}
diff --git a/web/modules/group/src/Entity/GroupContentType.php b/web/modules/group/src/Entity/GroupContentType.php
deleted file mode 100644
index 4a350f8ae7..0000000000
--- a/web/modules/group/src/Entity/GroupContentType.php
+++ /dev/null
@@ -1,247 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
-use Drupal\Core\Entity\EntityStorageInterface;
-
-/**
- * Defines the Group content type configuration entity.
- *
- * @ConfigEntityType(
- *   id = "group_content_type",
- *   label = @Translation("Group content type"),
- *   label_singular = @Translation("group content type"),
- *   label_plural = @Translation("group content types"),
- *   label_count = @PluralTranslation(
- *     singular = "@count group content type",
- *     plural = "@count group content types"
- *   ),
- *   handlers = {
- *     "storage" = "Drupal\group\Entity\Storage\GroupContentTypeStorage",
- *     "access" = "Drupal\group\Entity\Access\GroupContentTypeAccessControlHandler",
- *     "form" = {
- *       "add" = "Drupal\group\Entity\Form\GroupContentTypeForm",
- *       "edit" = "Drupal\group\Entity\Form\GroupContentTypeForm",
- *       "delete" = "Drupal\group\Entity\Form\GroupContentTypeDeleteForm"
- *     },
- *   },
- *   admin_permission = "administer group",
- *   config_prefix = "content_type",
- *   bundle_of = "group_content",
- *   static_cache = TRUE,
- *   entity_keys = {
- *     "id" = "id",
- *     "label" = "label"
- *   },
- *   config_export = {
- *     "id",
- *     "label",
- *     "description",
- *     "group_type",
- *     "content_plugin",
- *     "plugin_config",
- *   }
- * )
- */
-class GroupContentType extends ConfigEntityBundleBase implements GroupContentTypeInterface {
-
-  /**
-   * The machine name of the group content type.
-   *
-   * @var string
-   */
-  protected $id;
-
-  /**
-   * The human-readable name of the group content type.
-   *
-   * @var string
-   */
-  protected $label;
-
-  /**
-   * A brief description of the group content type.
-   *
-   * @var string
-   */
-  protected $description;
-
-  /**
-   * The group type ID for the group content type.
-   *
-   * @var string
-   */
-  protected $group_type;
-
-  /**
-   * The group content enabler plugin ID for the group content type.
-   *
-   * @var string
-   */
-  protected $content_plugin;
-
-  /**
-   * The group content enabler plugin configuration for group content type.
-   *
-   * @var array
-   */
-  protected $plugin_config = [];
-
-  /**
-   * The content enabler plugin instance.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerInterface
-   */
-  protected $pluginInstance;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function id() {
-    return $this->id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDescription() {
-    return $this->description;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setDescription($description) {
-    $this->description = $description;
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupType() {
-    return GroupType::load($this->getGroupTypeId());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupTypeId() {
-    return $this->group_type;
-  }
-
-  /**
-   * Returns the content enabler plugin manager.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   *   The group content plugin manager.
-   */
-  protected function getContentEnablerManager() {
-    return \Drupal::service('plugin.manager.group_content_enabler');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentPlugin() {
-    if (!isset($this->pluginInstance)) {
-      $configuration = $this->plugin_config;
-      $configuration['group_type_id'] = $this->getGroupTypeId();
-      $this->pluginInstance = $this->getContentEnablerManager()->createInstance($this->getContentPluginId(), $configuration);
-    }
-    return $this->pluginInstance;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentPluginId() {
-    return $this->content_plugin;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function updateContentPlugin(array $configuration) {
-    $this->plugin_config = $configuration;
-    $this->save();
-
-    // Make sure people get a fresh local plugin instance.
-    $this->pluginInstance = NULL;
-
-    // Make sure people get a freshly configured plugin collection.
-    $this->getContentEnablerManager()->clearCachedGroupTypeCollections($this->getGroupType());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function loadByContentPluginId($plugin_id) {
-    /** @var \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface $storage */
-    $storage = \Drupal::entityTypeManager()->getStorage('group_content_type');
-    return $storage->loadByContentPluginId($plugin_id);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function loadByEntityTypeId($entity_type_id) {
-    /** @var \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface $storage */
-    $storage = \Drupal::entityTypeManager()->getStorage('group_content_type');
-    return $storage->loadByEntityTypeId($entity_type_id);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
-    parent::postSave($storage, $update);
-
-    if (!$update) {
-      // When a new GroupContentType is saved, we clear the views data cache to
-      // make sure that all of the views data which relies on group content
-      // types is up to date.
-      if (\Drupal::moduleHandler()->moduleExists('views')) {
-        \Drupal::service('views.views_data')->clear();
-      }
-
-      // Run the post install tasks on the plugin.
-      $this->getContentPlugin()->postInstall();
-
-      // We need to reset the plugin ID map cache as it will be out of date now.
-      $this->getContentEnablerManager()->clearCachedPluginMaps();
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function postDelete(EntityStorageInterface $storage, array $entities) {
-    // When a GroupContentType is deleted, we clear the views data cache to make
-    // sure that all of the views data which relies on group content types is up
-    // to date.
-    if (\Drupal::moduleHandler()->moduleExists('views')) {
-      \Drupal::service('views.views_data')->clear();
-    }
-
-    /** @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager */
-    $plugin_manager = \Drupal::service('plugin.manager.group_content_enabler');
-
-    // We need to reset the plugin ID map cache as it will be out of date now.
-    $plugin_manager->clearCachedPluginMaps();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function calculateDependencies() {
-    // By adding the group type as a dependency, we ensure the group content
-    // type is deleted along with the group type.
-    $this->addDependency('config', $this->getGroupType()->getConfigDependencyName());
-
-    // Add the dependencies of the responsible content enabler plugin.
-    $this->addDependencies($this->getContentPlugin()->calculateDependencies());
-  }
-
-}
diff --git a/web/modules/group/src/Entity/GroupContentTypeInterface.php b/web/modules/group/src/Entity/GroupContentTypeInterface.php
deleted file mode 100644
index 69de987754..0000000000
--- a/web/modules/group/src/Entity/GroupContentTypeInterface.php
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\Core\Config\Entity\ConfigEntityInterface;
-use Drupal\Core\Entity\EntityDescriptionInterface;
-
-/**
- * Provides an interface defining a group content type entity.
- */
-interface GroupContentTypeInterface extends ConfigEntityInterface, EntityDescriptionInterface {
-
-  /**
-   * Gets the group type the content type was created for.
-   *
-   * @return \Drupal\group\Entity\GroupTypeInterface
-   *   The group type for which the content type was created.
-   */
-  public function getGroupType();
-
-  /**
-   * Gets the group type ID the content type was created for.
-   *
-   * @return string
-   *   The group type ID for which the content type was created.
-   */
-  public function getGroupTypeId();
-
-  /**
-   * Gets the content enabler plugin the content type uses.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerInterface
-   *   The content enabler plugin the content type uses.
-   */
-  public function getContentPlugin();
-
-  /**
-   * Gets the content enabler plugin ID the content type uses.
-   *
-   * @return string
-   *   The content enabler plugin ID the content type uses.
-   */
-  public function getContentPluginId();
-
-  /**
-   * Updates the configuration of the content enabler plugin.
-   * 
-   * Any keys that were left out will be reset to the default.
-   *
-   * @param array $configuration
-   *   An array of content enabler plugin configuration.
-   */
-  public function updateContentPlugin(array $configuration);
-
-  /**
-   * Loads group content type entities by their responsible plugin ID.
-   *
-   * @param string|string[] $plugin_id
-   *   The ID of the content enabler plugin or an array of plugin IDs. If more
-   *   than one plugin ID is provided, this will load all of the group content
-   *   types that match any of the provided plugin IDs.
-   *
-   * @return \Drupal\group\Entity\GroupContentTypeInterface[]
-   *   An array of group content type entities indexed by their IDs.
-   */
-  public static function loadByContentPluginId($plugin_id);
-
-  /**
-   * Loads group content type entities which could serve a given entity type.
-   *
-   * @param string $entity_type_id
-   *   An entity type ID which may be served by one or more group content types.
-   *
-   * @return \Drupal\group\Entity\GroupContentTypeInterface[]
-   *   An array of group content type entities which serve the given entity.
-   */
-  public static function loadByEntityTypeId($entity_type_id);
-  
-}
diff --git a/web/modules/group/src/Entity/GroupInterface.php b/web/modules/group/src/Entity/GroupInterface.php
deleted file mode 100644
index f6477fc59c..0000000000
--- a/web/modules/group/src/Entity/GroupInterface.php
+++ /dev/null
@@ -1,153 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\user\EntityOwnerInterface;
-use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\EntityChangedInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\user\UserInterface;
-
-/**
- * Provides an interface defining a Group entity.
- *
- * @ingroup group
- */
-interface GroupInterface extends ContentEntityInterface, EntityOwnerInterface, EntityChangedInterface {
-
-  /**
-   * Gets the group creation timestamp.
-   *
-   * @return int
-   *   Creation timestamp of the group.
-   */
-  public function getCreatedTime();
-
-  /**
-   * Returns the group type entity the group uses.
-   *
-   * @return \Drupal\group\Entity\GroupTypeInterface
-   */
-  public function getGroupType();
-
-  /**
-   * Adds a content entity as a group content entity.
-   *
-   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
-   *   The content entity to add to the group.
-   * @param string $plugin_id
-   *   The ID of the content enabler plugin to add the entity with.
-   * @param array $values
-   *   (optional) Extra values to add to the group content relationship. You
-   *   cannot overwrite the group ID (gid) or entity ID (entity_id).
-   */
-  public function addContent(ContentEntityInterface $entity, $plugin_id, $values = []);
-
-  /**
-   * Retrieves all GroupContent entities for the group.
-   *
-   * @param string $plugin_id
-   *   (optional) A content enabler plugin ID to filter on.
-   * @param array $filters
-   *   (optional) An associative array of extra filters where the keys are
-   *   property or field names and the values are the value to filter on.
-   *
-   * @return \Drupal\group\Entity\GroupContentInterface[]
-   *   A list of GroupContent entities matching the criteria.
-   */
-  public function getContent($plugin_id = NULL, $filters = []);
-
-  /**
-   * Retrieves all GroupContent entities for a specific entity.
-   *
-   * @param string $plugin_id
-   *   A content enabler plugin ID to filter on.
-   * @param int $id
-   *   The ID of the entity to retrieve the GroupContent entities for.
-   *
-   * @return \Drupal\group\Entity\GroupContentInterface[]
-   *   A list of GroupContent entities matching the criteria.
-   */
-  public function getContentByEntityId($plugin_id, $id);
-
-  /**
-   * Retrieves all group content for the group.
-   *
-   * Unlike GroupInterface::getContent(), this function actually returns the
-   * entities that were added to the group through GroupContent entities.
-   *
-   * @param string $plugin_id
-   *   (optional) A content enabler plugin ID to filter on.
-   * @param array $filters
-   *   (optional) An associative array of extra filters where the keys are
-   *   property or field names and the values are the value to filter on.
-   *
-   * @return \Drupal\Core\Entity\EntityInterface[]
-   *   A list of entities matching the criteria. This list does not have keys
-   *   that represent the entity IDs as we could have collisions that way.
-   *
-   * @see \Drupal\group\Entity\GroupInterface::getContent()
-   */
-  public function getContentEntities($plugin_id = NULL, $filters = []);
-
-  /**
-   * Adds a user as a member of the group.
-   *
-   * Does nothing if the user is already a member of the group.
-   *
-   * @param \Drupal\user\UserInterface $account
-   *   The user entity to add as a member.
-   * @param array $values
-   *   (optional) Extra values to add to the group membership, like the
-   *   'group_roles' field. You cannot overwrite the group ID (gid) or user ID
-   *   (entity_id) with this method. Leave blank to make the user just a member.
-   */
-  public function addMember(UserInterface $account, $values = []);
-
-  /**
-   * Removes a user as a member from the group.
-   *
-   * Does nothing if the user is not a member of the group.
-   *
-   * @param \Drupal\user\UserInterface $account
-   *   The user entity to remove as a member.
-   */
-  public function removeMember(UserInterface $account);
-
-  /**
-   * Retrieves a user's membership for the group.
-   *
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The user to load the membership for.
-   *
-   * @return \Drupal\group\GroupMembership|false
-   *   The loaded GroupMembership or FALSE if none was found.
-   */
-  public function getMember(AccountInterface $account);
-
-  /**
-   * Retrieves all group memberships for the group.
-   *
-   * @param string|array $roles
-   *   (optional) A group role machine name or a list of group role machine
-   *   names to filter on. Results only need to match on one role (IN query).
-   *
-   * @return \Drupal\group\GroupMembership[]
-   *   A list of GroupMembership objects representing the memberships.
-   */
-  public function getMembers($roles = NULL);
-
-  /**
-   * Checks whether a user has the requested permission.
-   *
-   * @param string $permission
-   *   The permission to check for.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account for which to check a permission.
-   *
-   * @return bool
-   *   Whether the user has the requested permission.
-   */
-  public function hasPermission($permission, AccountInterface $account);
-
-}
diff --git a/web/modules/group/src/Entity/GroupRole.php b/web/modules/group/src/Entity/GroupRole.php
deleted file mode 100644
index c47dd8cc6f..0000000000
--- a/web/modules/group/src/Entity/GroupRole.php
+++ /dev/null
@@ -1,334 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\Core\Config\Entity\ConfigEntityBase;
-use Drupal\Core\Entity\EntityStorageInterface;
-
-/**
- * Defines the Group role configuration entity.
- *
- * @ConfigEntityType(
- *   id = "group_role",
- *   label = @Translation("Group role"),
- *   label_singular = @Translation("group role"),
- *   label_plural = @Translation("group roles"),
- *   label_count = @PluralTranslation(
- *     singular = "@count group role",
- *     plural = "@count group roles"
- *   ),
- *   handlers = {
- *     "storage" = "Drupal\group\Entity\Storage\GroupRoleStorage",
- *     "access" = "Drupal\group\Entity\Access\GroupRoleAccessControlHandler",
- *     "form" = {
- *       "add" = "Drupal\group\Entity\Form\GroupRoleForm",
- *       "edit" = "Drupal\group\Entity\Form\GroupRoleForm",
- *       "delete" = "Drupal\group\Entity\Form\GroupRoleDeleteForm"
- *     },
- *     "route_provider" = {
- *       "html" = "Drupal\group\Entity\Routing\GroupRoleRouteProvider",
- *     },
- *     "list_builder" = "Drupal\group\Entity\Controller\GroupRoleListBuilder",
- *   },
- *   admin_permission = "administer group",
- *   config_prefix = "role",
- *   static_cache = TRUE,
- *   entity_keys = {
- *     "id" = "id",
- *     "weight" = "weight",
- *     "label" = "label"
- *   },
- *   links = {
- *     "add-form" = "/admin/group/types/manage/{group_type}/roles/add",
- *     "collection" = "/admin/group/types/manage/{group_type}/roles",
- *     "delete-form" = "/admin/group/types/manage/{group_type}/roles/{group_role}/delete",
- *     "edit-form" = "/admin/group/types/manage/{group_type}/roles/{group_role}",
- *     "permissions-form" = "/admin/group/types/manage/{group_type}/roles/{group_role}/permissions"
- *   },
- *   config_export = {
- *     "id",
- *     "label",
- *     "weight",
- *     "internal",
- *     "audience",
- *     "group_type",
- *     "permissions_ui",
- *     "permissions"
- *   }
- * )
- */
-class GroupRole extends ConfigEntityBase implements GroupRoleInterface {
-
-  /**
-   * The machine name of the group role.
-   *
-   * @var string
-   */
-  protected $id;
-
-  /**
-   * The human-readable name of the group role.
-   *
-   * @var string
-   */
-  protected $label;
-
-  /**
-   * The weight of the group role in administrative listings.
-   *
-   * @var int
-   */
-  protected $weight;
-
-  /**
-   * Whether the group role is used internally.
-   *
-   * Internal roles cannot be edited or assigned directly. They do not show in
-   * the list of group roles to edit or assign and do not have an individual
-   * permissions page either. Examples of these are the special group roles
-   * 'anonymous', 'outsider' and 'member'.
-   *
-   * @var bool
-   */
-  protected $internal = FALSE;
-
-  /**
-   * The audience the role is intended for.
-   *
-   * Supported values are: 'anonymous', 'outsider' or 'member'.
-   *
-   * @var string
-   */
-  protected $audience = 'member';
-
-  /**
-   * The ID of the group type this role belongs to.
-   *
-   * @var string
-   */
-  protected $group_type;
-
-  /**
-   * Whether the role shows in the default permissions UI.
-   *
-   * By default, group roles show on the permissions page regardless of their
-   * 'internal' property. If you want to hide a group role from that UI, you can
-   * do so by setting this to FALSE.
-   *
-   * @var bool
-   */
-  protected $permissions_ui = TRUE;
-
-  /**
-   * The permissions belonging to the group role.
-   *
-   * @var string[]
-   */
-  protected $permissions = [];
-
-  /**
-   * {@inheritdoc}
-   */
-  public function id() {
-    return $this->id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getWeight() {
-    return $this->get('weight');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setWeight($weight) {
-    $this->set('weight', $weight);
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isInternal() {
-    return $this->internal;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isAnonymous() {
-    return $this->audience == 'anonymous';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isOutsider() {
-    return $this->audience == 'outsider';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isMember() {
-    // Instead of checking whether the audience property is set to 'member', we
-    // check whether it isn't 'anonymous' or 'outsider'. Any unsupported value
-    // will therefore default to 'member'.
-    return !$this->isAnonymous() && !$this->isOutsider();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupType() {
-    return GroupType::load($this->group_type);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupTypeId() {
-    return $this->group_type;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function inPermissionsUI() {
-    return $this->permissions_ui;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPermissions() {
-    return $this->permissions;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function hasPermission($permission) {
-    return in_array($permission, $this->permissions);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function grantPermission($permission) {
-    return $this->grantPermissions([$permission]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function grantPermissions($permissions) {
-    $this->permissions = array_unique(array_merge($this->permissions, $permissions));
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function grantAllPermissions() {
-    $permissions = $this->getPermissionHandler()->getPermissionsByGroupType($this->getGroupType());
-
-    foreach ($permissions as $permission => $info) {
-      if (!in_array($this->audience, $info['allowed for'])) {
-        unset($permissions[$permission]);
-      }
-    }
-
-    return $this->grantPermissions(array_keys($permissions));
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function revokePermission($permission) {
-    return $this->revokePermissions([$permission]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function revokePermissions($permissions) {
-    $this->permissions = array_diff($this->permissions, $permissions);
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function changePermissions(array $permissions = []) {
-    // Grant new permissions to the role.
-    $grant = array_filter($permissions);
-    if (!empty($grant)) {
-      $this->grantPermissions(array_keys($grant));
-    }
-
-    // Revoke permissions from the role.
-    $revoke = array_diff_assoc($permissions, $grant);
-    if (!empty($revoke)) {
-      $this->revokePermissions(array_keys($revoke));
-    }
-
-    return $this;
-  }
-
-  /**
-   * Returns the group permission handler.
-   *
-   * @return \Drupal\group\Access\GroupPermissionHandler
-   *   The group permission handler.
-   */
-  protected function getPermissionHandler() {
-    return \Drupal::service('group.permissions');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function urlRouteParameters($rel) {
-    $uri_route_parameters = parent::urlRouteParameters($rel);
-    $uri_route_parameters['group_type'] = $this->getGroupTypeId();
-    return $uri_route_parameters;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function calculateDependencies() {
-    parent::calculateDependencies();
-    $this->addDependency('config', $this->getGroupType()->getConfigDependencyName());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function postLoad(EntityStorageInterface $storage, array &$entities) {
-    parent::postLoad($storage, $entities);
-    // Sort the queried roles by their weight.
-    // See \Drupal\Core\Config\Entity\ConfigEntityBase::sort().
-    uasort($entities, 'static::sort');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function preSave(EntityStorageInterface $storage) {
-    parent::preSave($storage);
-
-    if (!isset($this->weight) && ($group_roles = $storage->loadMultiple())) {
-      // Set a role weight to make this new role last.
-      $max = array_reduce($group_roles, function($max, $group_role) {
-        return $max > $group_role->weight ? $max : $group_role->weight;
-      });
-
-      $this->weight = $max + 1;
-    }
-  }
-
-}
diff --git a/web/modules/group/src/Entity/GroupRoleInterface.php b/web/modules/group/src/Entity/GroupRoleInterface.php
deleted file mode 100644
index 866e2a055c..0000000000
--- a/web/modules/group/src/Entity/GroupRoleInterface.php
+++ /dev/null
@@ -1,188 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\Core\Config\Entity\ConfigEntityInterface;
-
-/**
- * Provides an interface defining a group role entity.
- */
-interface GroupRoleInterface extends ConfigEntityInterface {
-
-  /**
-   * Returns the weight.
-   *
-   * @return int
-   *   The weight of this role.
-   */
-  public function getWeight();
-
-  /**
-   * Sets the weight to the given value.
-   *
-   * @param int $weight
-   *   The desired weight.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The group role this was called on.
-   */
-  public function setWeight($weight);
-
-  /**
-   * Returns whether the role is tied to a group type.
-   *
-   * @return bool
-   *   Whether the role is tied to a group type.
-   */
-  public function isInternal();
-
-  /**
-   * Returns whether the role is for an anonymous user.
-   *
-   * @return bool
-   *   Whether the role is for an anonymous user.
-   */
-  public function isAnonymous();
-
-  /**
-   * Returns whether the role is for an outsider.
-   *
-   * @return bool
-   *   Whether the role is for an outsider.
-   */
-  public function isOutsider();
-
-  /**
-   * Returns whether the role is for a member.
-   *
-   * @return bool
-   *   Whether the role is for a member.
-   */
-  public function isMember();
-
-  /**
-   * Returns the group type this role belongs to.
-   *
-   * @return \Drupal\group\Entity\GroupTypeInterface
-   *   The group type this role belongs to.
-   */
-  public function getGroupType();
-
-  /**
-   * Returns the ID of the group type this role belongs to.
-   *
-   * @return string
-   *   The ID of the group type this role belongs to.
-   */
-  public function getGroupTypeId();
-
-  /**
-   * Returns whether the role shows up in the default permissions UI.
-   *
-   * @return bool
-   *   Whether the role shows up in the default permissions UI.
-   */
-  public function inPermissionsUI();
-
-  /**
-   * Returns a list of permissions assigned to the role.
-   *
-   * @return array
-   *   The permissions assigned to the role.
-   */
-  public function getPermissions();
-
-  /**
-   * Checks if the role has a permission.
-   *
-   * @param string $permission
-   *   The permission to check for.
-   *
-   * @return bool
-   *   TRUE if the role has the permission, FALSE if not.
-   */
-  public function hasPermission($permission);
-
-  /**
-   * Grants a permission to the role.
-   *
-   * @param string $permission
-   *   The permission to grant.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The group role this was called on.
-   */
-  public function grantPermission($permission);
-
-  /**
-   * Grants multiple permissions to the role.
-   *
-   * @param string[] $permissions
-   *   The permissions to grant.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The group role this was called on.
-   */
-  public function grantPermissions($permissions);
-
-  /**
-   * Grants all available permissions to the role.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The group role this was called on.
-   */
-  public function grantAllPermissions();
-
-  /**
-   * Revokes a permission from the role.
-   *
-   * @param string $permission
-   *   The permission to revoke.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The group role this was called on.
-   */
-  public function revokePermission($permission);
-
-  /**
-   * Revokes multiple permissions from the role.
-   *
-   * @param string[] $permissions
-   *   The permissions to revoke.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The group role this was called on.
-   */
-  public function revokePermissions($permissions);
-
-  /**
-   * Changes permissions for the role.
-   *
-   * This function may be used to grant and revoke multiple permissions at once.
-   * For example, when a form exposes checkboxes to configure permissions for a
-   * role, the form submit handler may directly pass the submitted values for the
-   * checkboxes form element to this function.
-   *
-   * @param array $permissions
-   *   (optional) An associative array, where the key holds the permission name
-   *   and the value determines whether to grant or revoke that permission. Any
-   *   value that evaluates to TRUE will cause the permission to be granted.
-   *   Any value that evaluates to FALSE will cause the permission to be
-   *   revoked.
-   *   @code
-   *     [
-   *       'administer group' => 0,         // Revoke 'administer group'
-   *       'edit group' => FALSE,           // Revoke 'edit group'
-   *       'administer members' => 1,       // Grant 'administer members'
-   *       'leave group' => TRUE,           // Grant 'leave group'
-   *       'join group' => 'join group',    // Grant 'join group'
-   *     ]
-   *   @endcode
-   *   Existing permissions are not changed, unless specified in $permissions.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The group role this was called on.
-   */
-  public function changePermissions(array $permissions = []);
-
-}
diff --git a/web/modules/group/src/Entity/GroupType.php b/web/modules/group/src/Entity/GroupType.php
deleted file mode 100644
index 96905eb96c..0000000000
--- a/web/modules/group/src/Entity/GroupType.php
+++ /dev/null
@@ -1,321 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
-use Drupal\Core\Config\Entity\Exception\ConfigEntityIdLengthException;
-use Drupal\Core\Entity\EntityStorageInterface;
-
-/**
- * Defines the Group type configuration entity.
- *
- * @ConfigEntityType(
- *   id = "group_type",
- *   label = @Translation("Group type"),
- *   label_singular = @Translation("group type"),
- *   label_plural = @Translation("group types"),
- *   label_count = @PluralTranslation(
- *     singular = "@count group type",
- *     plural = "@count group types"
- *   ),
- *   handlers = {
- *     "access" = "Drupal\group\Entity\Access\GroupTypeAccessControlHandler",
- *     "form" = {
- *       "add" = "Drupal\group\Entity\Form\GroupTypeForm",
- *       "edit" = "Drupal\group\Entity\Form\GroupTypeForm",
- *       "delete" = "Drupal\group\Entity\Form\GroupTypeDeleteForm"
- *     },
- *     "route_provider" = {
- *       "html" = "Drupal\group\Entity\Routing\GroupTypeRouteProvider",
- *     },
- *     "list_builder" = "Drupal\group\Entity\Controller\GroupTypeListBuilder",
- *   },
- *   admin_permission = "administer group",
- *   config_prefix = "type",
- *   bundle_of = "group",
- *   static_cache = TRUE,
- *   entity_keys = {
- *     "id" = "id",
- *     "label" = "label"
- *   },
- *   links = {
- *     "add-form" = "/admin/group/types/add",
- *     "collection" = "/admin/group/types",
- *     "content-plugins" = "/admin/group/types/manage/{group_type}/content",
- *     "delete-form" = "/admin/group/types/manage/{group_type}/delete",
- *     "edit-form" = "/admin/group/types/manage/{group_type}",
- *     "permissions-form" = "/admin/group/types/manage/{group_type}/permissions"
- *   },
- *   config_export = {
- *     "id",
- *     "label",
- *     "description",
- *     "creator_roles",
- *   }
- * )
- */
-class GroupType extends ConfigEntityBundleBase implements GroupTypeInterface {
-
-  /**
-   * The machine name of the group type.
-   *
-   * @var string
-   */
-  protected $id;
-
-  /**
-   * The human-readable name of the group type.
-   *
-   * @var string
-   */
-  protected $label;
-
-  /**
-   * A brief description of the group type.
-   *
-   * @var string
-   */
-  protected $description;
-
-  /**
-   * The IDs of the group roles a group creator should receive.
-   *
-   * @var string[]
-   */
-  protected $creator_roles = [];
-
-  /**
-   * {@inheritdoc}
-   */
-  public function id() {
-    return $this->id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDescription() {
-    return $this->description;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setDescription($description) {
-    $this->description = $description;
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getRoles($include_internal = TRUE) {
-    $properties = ['group_type' => $this->id()];
-
-    // Exclude internal roles if told to.
-    if ($include_internal === FALSE) {
-      $properties['internal'] = FALSE;
-    }
-
-    return $this->entityTypeManager()
-      ->getStorage('group_role')
-      ->loadByProperties($properties);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getRoleIds($include_internal = TRUE) {
-    $query = $this->entityTypeManager()
-      ->getStorage('group_role')
-      ->getQuery()
-      ->condition('group_type', $this->id());
-
-    // Exclude internal roles if told to.
-    if ($include_internal === FALSE) {
-      $query->condition('internal', FALSE);
-    }
-
-    return $query->execute();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getAnonymousRole() {
-    return $this->entityTypeManager()
-      ->getStorage('group_role')
-      ->load($this->getAnonymousRoleId());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getAnonymousRoleId() {
-    return $this->id() . '-anonymous';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getOutsiderRole() {
-    return $this->entityTypeManager()
-      ->getStorage('group_role')
-      ->load($this->getOutsiderRoleId());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getOutsiderRoleId() {
-    return $this->id() . '-outsider';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getMemberRole() {
-    return $this->entityTypeManager()
-      ->getStorage('group_role')
-      ->load($this->getMemberRoleId());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getMemberRoleId() {
-    return $this->id() . '-member';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCreatorRoleIds() {
-    return $this->creator_roles;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function preSave(EntityStorageInterface $storage) {
-    // Throw an exception if the group type ID is longer than the limit.
-    if (strlen($this->id()) > GroupTypeInterface::ID_MAX_LENGTH) {
-      throw new ConfigEntityIdLengthException("Attempt to create a group type with an ID longer than " . GroupTypeInterface::ID_MAX_LENGTH . " characters: {$this->id()}.");
-    }
-
-    parent::preSave($storage);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
-    parent::postSave($storage, $update);
-
-    if (!$update) {
-      // Store the id in a short variable for readability.
-      $group_type_id = $this->id();
-
-      // @todo Remove this line when https://www.drupal.org/node/2645202 lands.
-      $this->setOriginalId($group_type_id);
-
-      // The code below will create the default group roles and the group
-      // content types for enforced plugins. It is extremely important that we
-      // only run this code if we are dealing with a new group type that was
-      // created through the API or UI; not through config synchronization.
-      //
-      // We do not create group roles or group content types for a synced group
-      // type because those should have been exported along with the group type.
-      if (!$this->isSyncing()) {
-        // Create the three special roles for the group type.
-        GroupRole::create([
-          'id' => $this->getAnonymousRoleId(),
-          'label' => t('Anonymous'),
-          'weight' => -102,
-          'internal' => TRUE,
-          'audience' => 'anonymous',
-          'group_type' => $group_type_id,
-        ])->save();
-        GroupRole::create([
-          'id' => $this->getOutsiderRoleId(),
-          'label' => t('Outsider'),
-          'weight' => -101,
-          'internal' => TRUE,
-          'audience' => 'outsider',
-          'group_type' => $group_type_id,
-        ])->save();
-        GroupRole::create([
-          'id' => $this->getMemberRoleId(),
-          'label' => t('Member'),
-          'weight' => -100,
-          'internal' => TRUE,
-          'group_type' => $group_type_id,
-        ])->save();
-
-        // Enable enforced content plugins for new group types.
-        $this->getContentEnablerManager()->installEnforced($this);
-      }
-    }
-  }
-
-  /**
-   * Returns the content enabler plugin manager.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   *   The group content plugin manager.
-   */
-  protected function getContentEnablerManager() {
-    return \Drupal::service('plugin.manager.group_content_enabler');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getInstalledContentPlugins() {
-    return $this->getContentEnablerManager()->getInstalled($this);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function hasContentPlugin($plugin_id) {
-    $installed = $this->getContentEnablerManager()->getInstalledIds($this);
-    return in_array($plugin_id, $installed);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentPlugin($plugin_id) {
-    return $this->getInstalledContentPlugins()->get($plugin_id);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function installContentPlugin($plugin_id, array $configuration = []) {
-    /** @var \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface $storage */
-    $storage = $this->entityTypeManager()->getStorage('group_content_type');
-    $storage->createFromPlugin($this, $plugin_id, $configuration)->save();
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function updateContentPlugin($plugin_id, array $configuration) {
-    $plugin = $this->getContentPlugin($plugin_id);
-    GroupContentType::load($plugin->getContentTypeConfigId())->updateContentPlugin($configuration);
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function uninstallContentPlugin($plugin_id) {
-    $plugin = $this->getContentPlugin($plugin_id);
-    GroupContentType::load($plugin->getContentTypeConfigId())->delete();
-    return $this;
-  }
-
-}
diff --git a/web/modules/group/src/Entity/GroupTypeInterface.php b/web/modules/group/src/Entity/GroupTypeInterface.php
deleted file mode 100644
index 0e92f3cf3b..0000000000
--- a/web/modules/group/src/Entity/GroupTypeInterface.php
+++ /dev/null
@@ -1,181 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity;
-
-use Drupal\Core\Config\Entity\ConfigEntityInterface;
-use Drupal\Core\Entity\EntityDescriptionInterface;
-
-/**
- * Provides an interface defining a group type entity.
- */
-interface GroupTypeInterface extends ConfigEntityInterface, EntityDescriptionInterface {
-
-  /**
-   * The maximum length of the ID, in characters.
-   *
-   * This is shorter than the default limit of 32 to allow group roles to have
-   * an ID which can be appended to the group type's ID without exceeding the
-   * default limit there. We leave of 10 characters to account for '-anonymous'.
-   */
-  const ID_MAX_LENGTH = 22;
-
-  /**
-   * Gets the group roles.
-   *
-   * @param bool $include_internal
-   *   (optional) Whether to include internal roles in the result. Defaults to
-   *   TRUE.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface[]
-   *   The group roles this group type uses.
-   */
-  public function getRoles($include_internal = TRUE);
-
-  /**
-   * Gets the role IDs.
-   *
-   * @param bool $include_internal
-   *   (optional) Whether to include internal roles in the result. Defaults to
-   *   TRUE.
-   *
-   * @return string[]
-   *   The ids of the group roles this group type uses.
-   */
-  public function getRoleIds($include_internal = TRUE);
-
-  /**
-   * Gets the generic anonymous group role for this group type.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The anonymous group role this group type uses.
-   */
-  public function getAnonymousRole();
-
-  /**
-   * Gets the generic anonymous role ID.
-   *
-   * @return string
-   *   The ID of the anonymous group role this group type uses.
-   */
-  public function getAnonymousRoleId();
-
-  /**
-   * Gets the generic outsider group role for this group type.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The outsider group role this group type uses.
-   */
-  public function getOutsiderRole();
-
-  /**
-   * Gets the generic outsider role ID.
-   *
-   * @return string
-   *   The ID of the outsider group role this group type uses.
-   */
-  public function getOutsiderRoleId();
-
-  /**
-   * Gets the generic member group role for this group type.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface
-   *   The generic member group role this group type uses.
-   */
-  public function getMemberRole();
-
-  /**
-   * Gets the generic member role ID.
-   *
-   * @return string
-   *   The ID of the generic member group role this group type uses.
-   */
-  public function getMemberRoleId();
-
-  /**
-   * Gets the IDs of the group roles a group creator should receive.
-   *
-   * @return string
-   *   The IDs of the group role the group creator should receive.
-   */
-  public function getCreatorRoleIds();
-
-  /**
-   * Returns the installed content enabler plugins for this group type.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerCollection
-   *   The group content plugin collection.
-   */
-  public function getInstalledContentPlugins();
-
-  /**
-   * Checks whether a content enabler plugin is installed for this group type.
-   *
-   * @param string $plugin_id
-   *   The ID of the content enabler plugin to check for.
-   *
-   * @return bool
-   *   Whether the content enabler plugin is installed.
-   */
-  public function hasContentPlugin($plugin_id);
-
-  /**
-   * Gets an installed content enabler plugin for this group type.
-   *
-   * Warning: In places where the plugin may not be installed on the group type,
-   * you should always run ::hasContentPlugin() first or you may risk ending up
-   * with crashes or unreliable data.
-   *
-   * @param string $plugin_id
-   *   The ID of the content enabler plugin.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerInterface
-   *   The installed content enabler plugin for the group type.
-   */
-  public function getContentPlugin($plugin_id);
-
-  /**
-   * Adds a content enabler plugin to this group type.
-   *
-   * @param string $plugin_id
-   *   The ID of the content enabler plugin to add.
-   * @param array $configuration
-   *   (optional) An array of content enabler plugin configuration.
-   *
-   * @return $this
-   *
-   * @deprecated in Group 1.0-beta3, will be removed before Group 1.0-rc1. Use
-   *   \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface::
-   *   createFromPlugin() instead.
-   */
-  public function installContentPlugin($plugin_id, array $configuration = []);
-
-  /**
-   * Updates the configuration of a content enabler plugin for this group type.
-   *
-   * @param string $plugin_id
-   *   The ID of the content enabler plugin to add.
-   * @param array $configuration
-   *   An array of content enabler plugin configuration.
-   *
-   * @return $this
-   *
-   * @deprecated in Group 1.0-beta3, will be removed before Group 1.0-rc1. Use
-   *   \Drupal\group\Entity\GroupContentTypeInterface::updateContentPlugin()
-   *   instead.
-   */
-  public function updateContentPlugin($plugin_id, array $configuration);
-
-  /**
-   * Removes a content enabler plugin from this group type.
-   *
-   * @param string $plugin_id
-   *   The content enabler plugin ID.
-   *
-   * @return $this
-   *
-   * @deprecated in Group 1.0-beta3, will be removed before Group 1.0-rc1. Use
-   *   \Drupal\group\Entity\GroupContentType::delete() instead.
-   */
-  public function uninstallContentPlugin($plugin_id);
-
-}
diff --git a/web/modules/group/src/Entity/Routing/GroupContentRouteProvider.php b/web/modules/group/src/Entity/Routing/GroupContentRouteProvider.php
deleted file mode 100644
index 71e3c94f61..0000000000
--- a/web/modules/group/src/Entity/Routing/GroupContentRouteProvider.php
+++ /dev/null
@@ -1,217 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Routing;
-
-use Drupal\Core\Entity\EntityFieldManagerInterface;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Provides routes for group content.
- */
-class GroupContentRouteProvider extends DefaultHtmlRouteProvider {
-
-  /**
-   * The group content enabler plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * Constructs a new GroupContentRouteProvider.
-   *
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content enabler plugin manager.
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
-   *   The entity field manager.
-   */
-  public function __construct(GroupContentEnablerManagerInterface $plugin_manager, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager) {
-    parent::__construct($entity_type_manager, $entity_field_manager);
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
-    return new static(
-      $container->get('plugin.manager.group_content_enabler'),
-      $container->get('entity_type.manager'),
-      $container->get('entity_field.manager')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getRoutes(EntityTypeInterface $entity_type) {
-    $collection = parent::getRoutes($entity_type);
-
-    if ($create_page_route = $this->getCreatePageRoute($entity_type)) {
-      $collection->add("entity.group_content.create_page", $create_page_route);
-    }
-
-    if ($create_form_route = $this->getCreateFormRoute($entity_type)) {
-      $collection->add("entity.group_content.create_form", $create_form_route);
-    }
-
-    return $collection;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getAddPageRoute(EntityTypeInterface $entity_type) {
-    if ($entity_type->hasLinkTemplate('add-page') && $entity_type->getKey('bundle')) {
-      $route = new Route($entity_type->getLinkTemplate('add-page'));
-      $route
-        ->setDefault('_controller', '\Drupal\group\Entity\Controller\GroupContentController::addPage')
-        ->setDefault('_title', 'Relate content to group')
-        ->setRequirement('_group_content_create_any_access', 'TRUE')
-        ->setOption('_group_operation_route', TRUE);
-
-      return $route;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getAddFormRoute(EntityTypeInterface $entity_type) {
-    if ($entity_type->hasLinkTemplate('add-form')) {
-      $route = new Route($entity_type->getLinkTemplate('add-form'));
-      $route
-        ->setDefaults([
-          '_controller' => '\Drupal\group\Entity\Controller\GroupContentController::addForm',
-          // @todo Let forms set title?
-          '_title_callback' => '\Drupal\group\Entity\Controller\GroupContentController::addFormTitle',
-        ])
-        ->setRequirement('_group_content_create_access', 'TRUE')
-        ->setOption('_group_operation_route', TRUE);
-
-      return $route;
-    }
-  }
-
-  /**
-   * Gets the create-page route.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
-   *   The entity type.
-   *
-   * @return \Symfony\Component\Routing\Route|null
-   *   The generated route, if available.
-   */
-  protected function getCreatePageRoute(EntityTypeInterface $entity_type) {
-    if ($entity_type->hasLinkTemplate('create-page') && $entity_type->getKey('bundle')) {
-      $route = new Route($entity_type->getLinkTemplate('create-page'));
-      $route
-        ->setDefault('_controller', '\Drupal\group\Entity\Controller\GroupContentController::addPage')
-        ->setDefault('_title', 'Create content in group')
-        ->setDefault('create_mode', TRUE)
-        ->setRequirement('_group_content_create_any_entity_access', 'TRUE')
-        ->setOption('_group_operation_route', TRUE);
-
-      return $route;
-    }
-  }
-
-  /**
-   * Gets the create-form route.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
-   *   The entity type.
-   *
-   * @return \Symfony\Component\Routing\Route|null
-   *   The generated route, if available.
-   */
-  protected function getCreateFormRoute(EntityTypeInterface $entity_type) {
-    if ($entity_type->hasLinkTemplate('create-form')) {
-      $route = new Route($entity_type->getLinkTemplate('create-form'));
-      $route
-        ->setDefaults([
-          '_controller' => '\Drupal\group\Entity\Controller\GroupContentController::createForm',
-          // @todo Let forms set title?
-          '_title_callback' => '\Drupal\group\Entity\Controller\GroupContentController::createFormTitle',
-        ])
-        ->setRequirement('_group_content_create_entity_access', 'TRUE')
-        ->setOption('_group_operation_route', TRUE);
-
-      return $route;
-    }
-  }
-
-  /**
-   * Gets the collection route.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
-   *   The entity type.
-   *
-   * @return \Symfony\Component\Routing\Route|null
-   *   The generated route, if available.
-   */
-  protected function getCollectionRoute(EntityTypeInterface $entity_type) {
-    if ($entity_type->hasLinkTemplate('collection') && $entity_type->hasListBuilderClass()) {
-      $route = new Route($entity_type->getLinkTemplate('collection'));
-      $route
-        ->addDefaults([
-          '_entity_list' => 'group_content',
-          '_title_callback' => '\Drupal\group\Entity\Controller\GroupContentController::collectionTitle',
-        ])
-        ->setRequirement('_group_permission', "access content overview")
-        ->setOption('_group_operation_route', TRUE)
-        ->setOption('parameters', [
-          'group' => ['type' => 'entity:group'],
-        ]);
-
-      return $route;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getCanonicalRoute(EntityTypeInterface $entity_type) {
-    return parent::getCanonicalRoute($entity_type)
-      ->setRequirement('_group_owns_content', 'TRUE')
-      ->setOption('parameters', [
-        'group' => ['type' => 'entity:group'],
-        'group_content' => ['type' => 'entity:group_content'],
-      ]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getEditFormRoute(EntityTypeInterface $entity_type) {
-    return parent::getEditFormRoute($entity_type)
-      ->setDefault('_title_callback', '\Drupal\group\Entity\Controller\GroupContentController::editFormTitle')
-      ->setRequirement('_group_owns_content', 'TRUE')
-      ->setOption('_group_operation_route', TRUE)
-      ->setOption('parameters', [
-        'group' => ['type' => 'entity:group'],
-        'group_content' => ['type' => 'entity:group_content'],
-      ]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getDeleteFormRoute(EntityTypeInterface $entity_type) {
-    return parent::getDeleteFormRoute($entity_type)
-      ->setRequirement('_group_owns_content', 'TRUE')
-      ->setOption('_group_operation_route', TRUE)
-      ->setOption('parameters', [
-        'group' => ['type' => 'entity:group'],
-        'group_content' => ['type' => 'entity:group_content'],
-      ]);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Routing/GroupRoleRouteProvider.php b/web/modules/group/src/Entity/Routing/GroupRoleRouteProvider.php
deleted file mode 100644
index 7daa620c1e..0000000000
--- a/web/modules/group/src/Entity/Routing/GroupRoleRouteProvider.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Routing;
-
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider;
-
-/**
- * Provides routes for group roles.
- */
-class GroupRoleRouteProvider extends DefaultHtmlRouteProvider {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getAddFormRoute(EntityTypeInterface $entity_type) {
-    if ($route = parent::getAddFormRoute($entity_type)) {
-      $route->setOption('parameters', ['group_type' => ['type' => 'entity:group_type']]);
-      return $route;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getEditFormRoute(EntityTypeInterface $entity_type) {
-    if ($route = parent::getEditFormRoute($entity_type)) {
-      // @todo Remove title part when https://www.drupal.org/node/2827739 lands.
-      $route->setDefault('_title_callback', '\Drupal\group\Entity\Controller\GroupRoleController::editTitle');
-      $route->setOption('parameters', ['group_type' => ['type' => 'entity:group_type']]);
-      return $route;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getDeleteFormRoute(EntityTypeInterface $entity_type) {
-    if ($route = parent::getDeleteFormRoute($entity_type)) {
-      // @todo Remove title part when https://www.drupal.org/node/2827739 lands.
-      $route->setDefault('_title_callback', '\Drupal\group\Entity\Controller\GroupRoleController::deleteTitle');
-      $route->setOption('parameters', ['group_type' => ['type' => 'entity:group_type']]);
-      return $route;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getCollectionRoute(EntityTypeInterface $entity_type) {
-    if ($route = parent::getCollectionRoute($entity_type)) {
-      // @todo Remove title part when https://www.drupal.org/node/2767025 lands.
-      $route->setDefault('_title', 'Group roles');
-      $route->setDefault('_title_arguments', []);
-      $route->setOption('parameters', ['group_type' => ['type' => 'entity:group_type']]);
-      return $route;
-    }
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Routing/GroupRouteProvider.php b/web/modules/group/src/Entity/Routing/GroupRouteProvider.php
deleted file mode 100644
index 3429c36920..0000000000
--- a/web/modules/group/src/Entity/Routing/GroupRouteProvider.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Routing;
-
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider;
-
-/**
- * Provides routes for groups.
- */
-class GroupRouteProvider extends DefaultHtmlRouteProvider {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getAddPageRoute(EntityTypeInterface $entity_type) {
-    if ($route = parent::getAddPageRoute($entity_type)) {
-      $route->setOption('_group_operation_route', TRUE);
-      return $route;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getAddFormRoute(EntityTypeInterface $entity_type) {
-    if ($route = parent::getAddFormRoute($entity_type)) {
-      $route->setOption('_group_operation_route', TRUE);
-      return $route;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getEditFormRoute(EntityTypeInterface $entity_type) {
-    if ($route = parent::getEditFormRoute($entity_type)) {
-      $route->setOption('_group_operation_route', TRUE);
-      return $route;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getDeleteFormRoute(EntityTypeInterface $entity_type) {
-    if ($route = parent::getDeleteFormRoute($entity_type)) {
-      $route->setOption('_group_operation_route', TRUE);
-      return $route;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getCollectionRoute(EntityTypeInterface $entity_type) {
-    // @todo Remove this method when https://www.drupal.org/node/2767025 lands.
-    if ($route = parent::getCollectionRoute($entity_type)) {
-      $route->setDefault('_title', 'Groups');
-      $route->setDefault('_title_arguments', []);
-      return $route;
-    }
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Routing/GroupTypeRouteProvider.php b/web/modules/group/src/Entity/Routing/GroupTypeRouteProvider.php
deleted file mode 100644
index a4b175824a..0000000000
--- a/web/modules/group/src/Entity/Routing/GroupTypeRouteProvider.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Routing;
-
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider;
-
-/**
- * Provides routes for group types.
- */
-class GroupTypeRouteProvider extends DefaultHtmlRouteProvider {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getCollectionRoute(EntityTypeInterface $entity_type) {
-    // @todo Remove this method when https://www.drupal.org/node/2767025 lands.
-    if ($route = parent::getCollectionRoute($entity_type)) {
-      $route->setDefault('_title', 'Group types');
-      $route->setDefault('_title_arguments', []);
-      return $route;
-    }
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Storage/GroupContentStorage.php b/web/modules/group/src/Entity/Storage/GroupContentStorage.php
deleted file mode 100644
index b263e0ffed..0000000000
--- a/web/modules/group/src/Entity/Storage/GroupContentStorage.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Storage;
-
-use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
-use Drupal\group\Entity\GroupInterface;
-
-/**
- * Defines the storage handler class for group content entities.
- *
- * This extends the base storage class, adding required special handling for
- * loading group content entities based on group and plugin information.
- */
-class GroupContentStorage extends SqlContentEntityStorage implements GroupContentStorageInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function loadByGroup(GroupInterface $group, $plugin_id = NULL, $filters = []) {
-    $properties = ['gid' => $group->id()] + $filters;
-
-    // If a plugin ID was provided, set the group content type ID for it.
-    if (isset($plugin_id)) {
-      /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-      $plugin = $group->getGroupType()->getContentPlugin($plugin_id);
-      $properties['type'] = $plugin->getContentTypeConfigId();
-    }
-
-    return $this->loadByProperties($properties);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Storage/GroupContentStorageInterface.php b/web/modules/group/src/Entity/Storage/GroupContentStorageInterface.php
deleted file mode 100644
index a7ac2e6dc2..0000000000
--- a/web/modules/group/src/Entity/Storage/GroupContentStorageInterface.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Storage;
-
-use Drupal\Core\Entity\ContentEntityStorageInterface;
-use Drupal\group\Entity\GroupInterface;
-
-/**
- * Defines an interface for group content entity storage classes.
- */
-interface GroupContentStorageInterface extends ContentEntityStorageInterface {
-
-  /**
-   * Retrieves all GroupContent entities for a group.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group entity to load the group content entities for.
-   * @param string $plugin_id
-   *   (optional) A content enabler plugin ID to filter on.
-   * @param array $filters
-   *   (optional) An associative array of extra filters where the keys are
-   *   property or field names and the values are the value to filter on.
-   *
-   * @return \Drupal\group\Entity\GroupContentInterface[]
-   *   A list of GroupContent entities matching the criteria.
-   */
-  public function loadByGroup(GroupInterface $group, $plugin_id = NULL, $filters = []);
-
-}
diff --git a/web/modules/group/src/Entity/Storage/GroupContentTypeStorage.php b/web/modules/group/src/Entity/Storage/GroupContentTypeStorage.php
deleted file mode 100644
index e512b9965d..0000000000
--- a/web/modules/group/src/Entity/Storage/GroupContentTypeStorage.php
+++ /dev/null
@@ -1,121 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Storage;
-
-use Drupal\Component\Uuid\UuidInterface;
-use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Config\Entity\ConfigEntityStorage;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Language\LanguageManagerInterface;
-use Drupal\group\Entity\GroupTypeInterface;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Defines the storage handler class for group content type entities.
- *
- * This extends the base storage class, adding required special handling for
- * loading group content type entities based on group type and plugin ID.
- */
-class GroupContentTypeStorage extends ConfigEntityStorage implements GroupContentTypeStorageInterface {
-
-  /**
-   * The group content plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * Constructs a GroupContentTypeStorage object.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
-   *   The entity type definition.
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content enabler manager.
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *   The config factory service.
-   * @param \Drupal\Component\Uuid\UuidInterface $uuid_service
-   *   The UUID service.
-   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
-   *   The language manager.
-   */
-  public function __construct(EntityTypeInterface $entity_type, GroupContentEnablerManagerInterface $plugin_manager, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager) {
-    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
-    return new static(
-      $entity_type,
-      $container->get('plugin.manager.group_content_enabler'),
-      $container->get('config.factory'),
-      $container->get('uuid'),
-      $container->get('language_manager')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function loadByGroupType(GroupTypeInterface $group_type) {
-    return $this->loadByProperties(['group_type' => $group_type->id()]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function loadByContentPluginId($plugin_id) {
-    return $this->loadByProperties(['content_plugin' => $plugin_id]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function loadByEntityTypeId($entity_type_id) {
-    $plugin_ids = [];
-    
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    foreach ($this->pluginManager->getAll() as $plugin_id => $plugin) {
-      if ($plugin->getEntityTypeId() === $entity_type_id) {
-        $plugin_ids[] = $plugin_id;
-      }
-    }
-
-    // If no responsible group content plugins were found, we return nothing.
-    if (empty($plugin_ids)) {
-      return [];
-    }
-
-    // Otherwise load all group content types being handled by gathered plugins.
-    return $this->loadByContentPluginId($plugin_ids);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function createFromPlugin(GroupTypeInterface $group_type, $plugin_id, array $configuration = []) {
-    // Add the group type ID to the configuration.
-    $configuration['group_type_id'] = $group_type->id();
-
-    // Instantiate the plugin we are installing.
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    $plugin = $this->pluginManager->createInstance($plugin_id, $configuration);
-
-    // Create the group content type using plugin generated info.
-    $values = [
-      'id' => $plugin->getContentTypeConfigId(),
-      'label' => $plugin->getContentTypeLabel(),
-      'description' => $plugin->getContentTypeDescription(),
-      'group_type' => $group_type->id(),
-      'content_plugin' => $plugin_id,
-      'plugin_config' => $plugin->getConfiguration(),
-    ];
-    
-    return $this->create($values);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Storage/GroupContentTypeStorageInterface.php b/web/modules/group/src/Entity/Storage/GroupContentTypeStorageInterface.php
deleted file mode 100644
index 4ec35987e6..0000000000
--- a/web/modules/group/src/Entity/Storage/GroupContentTypeStorageInterface.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Storage;
-
-use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
-use Drupal\group\Entity\GroupTypeInterface;
-
-/**
- * Defines an interface for group content type entity storage classes.
- */
-interface GroupContentTypeStorageInterface extends ConfigEntityStorageInterface {
-
-  /**
-   * Retrieves all group content types for a group type.
-   *
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   The group type to load the group content types for.
-   *
-   * @return \Drupal\group\Entity\GroupContentTypeInterface[]
-   *   An array of group content types indexed by their IDs.
-   */
-  public function loadByGroupType(GroupTypeInterface $group_type);
-
-  /**
-   * Retrieves group content types by their responsible plugin ID.
-   *
-   * @param string|string[] $plugin_id
-   *   The ID of the content enabler plugin or an array of plugin IDs. If more
-   *   than one plugin ID is provided, this will load all of the group content
-   *   types that match any of the provided plugin IDs.
-   *
-   * @return \Drupal\group\Entity\GroupContentTypeInterface[]
-   *   An array of group content types indexed by their IDs.
-   */
-  public function loadByContentPluginId($plugin_id);
-
-  /**
-   * Retrieves group content types which could serve a given entity type.
-   *
-   * @param string $entity_type_id
-   *   An entity type ID which may be served by one or more group content types.
-   *
-   * @return \Drupal\group\Entity\GroupContentTypeInterface[]
-   *   An array of group content types indexed by their IDs.
-   */
-  public function loadByEntityTypeId($entity_type_id);
-
-  /**
-   * Creates a group content type for a group type using a specific plugin.
-   *
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   The group type to create the group content type for.
-   * @param string $plugin_id
-   *   The ID of the content enabler plugin to use.
-   * @param array $configuration
-   *   (optional) An array of content enabler plugin configuration.
-   * 
-   * @return \Drupal\group\Entity\GroupContentTypeInterface
-   *   A new, unsaved GroupContentType entity.
-   */
-  public function createFromPlugin(GroupTypeInterface $group_type, $plugin_id, array $configuration = []);
-
-}
diff --git a/web/modules/group/src/Entity/Storage/GroupRoleStorage.php b/web/modules/group/src/Entity/Storage/GroupRoleStorage.php
deleted file mode 100644
index ca7a19d077..0000000000
--- a/web/modules/group/src/Entity/Storage/GroupRoleStorage.php
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Storage;
-
-use Drupal\Component\Uuid\UuidInterface;
-use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Config\Entity\ConfigEntityStorage;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Language\LanguageManagerInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupInterface;
-use Drupal\group\GroupMembershipLoaderInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Defines the storage handler class for group role entities.
- *
- * This extends the base storage class, adding required special handling for
- * loading group role entities based on user and group information.
- */
-class GroupRoleStorage extends ConfigEntityStorage implements GroupRoleStorageInterface {
-
-  /**
-   * Static cache of a user's group role IDs.
-   *
-   * @todo Perhaps we need to be able to clear this cache during runtime?
-   *
-   * @var array
-   */
-  protected $userGroupRoleIds = [];
-
-  /**
-   * The group membership loader.
-   *
-   * @var \Drupal\group\GroupMembershipLoaderInterface
-   */
-  protected $membershipLoader;
-
-  /**
-   * Constructs a GroupRoleStorage object.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
-   *   The entity type definition.
-   * @param \Drupal\group\GroupMembershipLoaderInterface $membership_loader
-   *   The group membership loader.
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *   The config factory service.
-   * @param \Drupal\Component\Uuid\UuidInterface $uuid_service
-   *   The UUID service.
-   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
-   *   The language manager.
-   */
-  public function __construct(EntityTypeInterface $entity_type, GroupMembershipLoaderInterface $membership_loader, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager) {
-    parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
-    $this->membershipLoader = $membership_loader;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
-    return new static(
-      $entity_type,
-      $container->get('group.membership_loader'),
-      $container->get('config.factory'),
-      $container->get('uuid'),
-      $container->get('language_manager')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function loadByUserAndGroup(AccountInterface $account, GroupInterface $group, $include_implied = TRUE) {
-    $uid = $account->id();
-    $gid = $group->id();
-
-    if (!isset($this->userGroupRoleIds[$uid][$gid])) {
-      $ids = [];
-
-      // Get the IDs from the 'group_roles' field, without loading the roles.
-      if ($membership = $this->membershipLoader->load($group, $account)) {
-        foreach ($membership->getGroupContent()->group_roles as $group_role_ref) {
-          $ids[] = $group_role_ref->target_id;
-        }
-      }
-
-      // Add the implied group role IDs.
-      if ($include_implied) {
-        if ($membership !== FALSE) {
-          $ids[] = $group->getGroupType()->getMemberRoleId();
-        }
-        else {
-          $ids[] = $account->isAnonymous()
-            ? $group->getGroupType()->getAnonymousRoleId()
-            : $group->getGroupType()->getOutsiderRoleId();
-        }
-      }
-
-      $this->userGroupRoleIds[$uid][$gid] = $ids;
-    }
-
-    return $this->loadMultiple($this->userGroupRoleIds[$uid][$gid]);
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Storage/GroupRoleStorageInterface.php b/web/modules/group/src/Entity/Storage/GroupRoleStorageInterface.php
deleted file mode 100644
index 026958675a..0000000000
--- a/web/modules/group/src/Entity/Storage/GroupRoleStorageInterface.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Storage;
-
-use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupInterface;
-
-/**
- * Defines an interface for group role entity storage classes.
- */
-interface GroupRoleStorageInterface extends ConfigEntityStorageInterface {
-
-  /**
-   * Retrieves all GroupRole entities for a user within a group.
-   *
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account to load the group role entities for.
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group entity to find the user's role entities in.
-   * @param boolean $include_implied
-   *   (optional) Whether to include the implied roles 'anonymous', 'outsider'
-   *   and 'member'. Defaults to TRUE.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface[]
-   *   The group roles matching the criteria.
-   */
-  public function loadByUserAndGroup(AccountInterface $account, GroupInterface $group, $include_implied = TRUE);
-
-}
diff --git a/web/modules/group/src/Entity/ViewBuilder/GroupViewBuilder.php b/web/modules/group/src/Entity/ViewBuilder/GroupViewBuilder.php
deleted file mode 100644
index 8bfa533937..0000000000
--- a/web/modules/group/src/Entity/ViewBuilder/GroupViewBuilder.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\ViewBuilder;
-
-use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\EntityViewBuilder;
-
-/**
- * View builder handler for groups.
- *
- * @todo Keep an eye on https://www.drupal.org/node/2791571.
- */
-class GroupViewBuilder extends EntityViewBuilder {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function alterBuild(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
-    /** @var \Drupal\group\Entity\GroupInterface $entity */
-    parent::alterBuild($build, $entity, $display, $view_mode);
-    if ($entity->id()) {
-      $build['#contextual_links']['group'] = array(
-        'route_parameters' => array('group' => $entity->id()),
-        'metadata' => array('changed' => $entity->getChangedTime()),
-      );
-    }
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Views/GroupContentViewsData.php b/web/modules/group/src/Entity/Views/GroupContentViewsData.php
deleted file mode 100644
index 62eb94ade8..0000000000
--- a/web/modules/group/src/Entity/Views/GroupContentViewsData.php
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Views;
-
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\StringTranslation\TranslationInterface;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Drupal\views\EntityViewsData;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides the views data for the group content entity type.
- */
-class GroupContentViewsData extends EntityViewsData {
-
-  /**
-   * The group content enabler plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * The entity manager set but not declared in the parent class.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface;
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a GroupContentViewsData object.
-   *
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content enabler plugin manager.
-   */
-  function __construct(EntityTypeInterface $entity_type, SqlEntityStorageInterface $storage_controller, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, TranslationInterface $translation_manager, GroupContentEnablerManagerInterface $plugin_manager) {
-    parent::__construct($entity_type, $storage_controller, $entity_manager, $module_handler, $translation_manager);
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
-    return new static(
-      $entity_type,
-      $container->get('entity.manager')->getStorage($entity_type->id()),
-      $container->get('entity.manager'),
-      $container->get('module_handler'),
-      $container->get('string_translation'),
-      $container->get('plugin.manager.group_content_enabler')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getViewsData() {
-    $data = parent::getViewsData();
-
-    // Add a custom numeric argument for the parent group ID that allows us to
-    // use replacement titles with the parent group's label.
-    $data['group_content_field_data']['gid']['argument'] = [
-      'id' => 'group_id',
-      'numeric' => TRUE,
-    ];
-    
-    // Get the data table for GroupContent entities.
-    $data_table = $this->entityType->getDataTable();
-
-    // Unset the 'entity_id' field relationship as we want a more powerful one.
-    // @todo Eventually, we may want to replace all of 'entity_id'.
-    unset($data[$data_table]['entity_id']['relationship']);
-
-    /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
-    $entity_types = $this->entityManager->getDefinitions();
-
-    // Add views data for all defined plugins so modules can provide default
-    // views even though their plugins may not have been installed yet.
-    foreach ($this->pluginManager->getAll() as $plugin) {
-      $entity_type_id = $plugin->getEntityTypeId();
-      $entity_type = $entity_types[$entity_type_id];
-      $entity_data_table = $entity_type->getDataTable() ?: $entity_type->getBaseTable();
-
-      // Create a unique field name for this views field.
-      $field_name = 'gc__' . $entity_type_id;
-
-      // We only add one 'group_content' relationship per entity type.
-      if (isset($data[$entity_data_table][$field_name])) {
-        continue;
-      }
-
-      $t_args = [
-        '@entity_type' => $entity_type->getLabel(),
-      ];
-
-      // This relationship will allow a group content entity to easily map to a
-      // content entity that it ties to a group, optionally filtering by plugin.
-      $data[$data_table][$field_name] = array(
-        'title' => t('@entity_type from group content', $t_args),
-        'help' => t('Relates to the @entity_type entity the group content represents.', $t_args),
-        'relationship' => array(
-          'group' => $entity_type->getLabel(),
-          'base' => $entity_data_table,
-          'base field' => $entity_type->getKey('id'),
-          'relationship field' => 'entity_id',
-          'id' => 'group_content_to_entity',
-          'label' => t('Group content @entity_type', $t_args),
-          'target_entity_type' => $entity_type_id,
-        ),
-      );
-    }
-
-    return $data;
-  }
-
-}
diff --git a/web/modules/group/src/Entity/Views/GroupViewsData.php b/web/modules/group/src/Entity/Views/GroupViewsData.php
deleted file mode 100644
index d0c39096f1..0000000000
--- a/web/modules/group/src/Entity/Views/GroupViewsData.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-namespace Drupal\group\Entity\Views;
-
-use Drupal\views\EntityViewsData;
-
-/**
- * Provides the views data for the group entity type.
- */
-class GroupViewsData extends EntityViewsData {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getViewsData() {
-    $data = parent::getViewsData();
-
-    $data['groups_field_data']['id']['argument'] = [
-      'id' => 'group_id',
-      'name field' => 'label',
-      'numeric' => TRUE,
-    ];
-
-    $data['groups_field_data']['group_content_id']['relationship'] = array(
-      'title' => $this->t('Group content'),
-      'help' => $this->t('Relate to the group content entities. From there you can relate to the actual grouped entities.'),
-      'id' => 'group_to_group_content',
-      'base' => 'group_content_field_data',
-      'base field' => 'gid',
-      'field' => 'id',
-      'label' => $this->t('Group content'),
-    );
-
-    return $data;
-  }
-
-}
diff --git a/web/modules/group/src/Form/GroupJoinForm.php b/web/modules/group/src/Form/GroupJoinForm.php
deleted file mode 100644
index 8cf1a11c07..0000000000
--- a/web/modules/group/src/Form/GroupJoinForm.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-
-namespace Drupal\group\Form;
-
-use Drupal\group\Entity\Form\GroupContentForm;
-use Drupal\Core\Form\FormStateInterface;
-
-/**
- * Provides a form for joining a group.
- */
-class GroupJoinForm extends GroupContentForm {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function form(array $form, FormStateInterface $form_state) {
-    $form = parent::form($form, $form_state);
-    $form['entity_id']['#access'] = FALSE;
-    $form['group_roles']['#access'] = FALSE;
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function actions(array $form, FormStateInterface $form_state) {
-    $actions = parent::actions($form, $form_state);
-    $actions['submit']['#value'] = $this->t('Join group');
-    return $actions;
-  }
-
-}
diff --git a/web/modules/group/src/Form/GroupLeaveForm.php b/web/modules/group/src/Form/GroupLeaveForm.php
deleted file mode 100644
index 202cc67562..0000000000
--- a/web/modules/group/src/Form/GroupLeaveForm.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-namespace Drupal\group\Form;
-
-use Drupal\group\Entity\Form\GroupContentDeleteForm;
-
-/**
- * Provides a form for leaving a group.
- */
-class GroupLeaveForm extends GroupContentDeleteForm {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getQuestion() {
-    $message = 'Are you sure you want to leave %group?';
-    $replace = ['%group' => $this->getEntity()->getGroup()->label()];
-    return $this->t($message, $replace);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getConfirmText() {
-    return $this->t('Leave group');
-  }
-
-}
diff --git a/web/modules/group/src/Form/GroupPermissionsForm.php b/web/modules/group/src/Form/GroupPermissionsForm.php
deleted file mode 100644
index f21bd0e706..0000000000
--- a/web/modules/group/src/Form/GroupPermissionsForm.php
+++ /dev/null
@@ -1,259 +0,0 @@
-<?php
-
-namespace Drupal\group\Form;
-
-use Drupal\Component\Render\FormattableMarkup;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Form\FormBase;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\group\Access\GroupPermissionHandlerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides the group permissions administration form.
- */
-abstract class GroupPermissionsForm extends FormBase {
-
-  /**
-   * The permission handler.
-   *
-   * @var \Drupal\group\Access\GroupPermissionHandlerInterface
-   */
-  protected $groupPermissionHandler;
-
-  /**
-   * The module handler.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
-   * Constructs a new GroupPermissionsForm.
-   *
-   * @param \Drupal\group\Access\GroupPermissionHandlerInterface $permission_handler
-   *   The group permission handler.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
-   */
-  public function __construct(GroupPermissionHandlerInterface $permission_handler, ModuleHandlerInterface $module_handler) {
-    $this->groupPermissionHandler = $permission_handler;
-    $this->moduleHandler = $module_handler;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('group.permissions'),
-      $container->get('module_handler')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-    return 'group_admin_permissions';
-  }
-
-  /**
-   * Gets a few basic instructions to show the user.
-   *
-   * @return array
-   *   A render array to display atop the form.
-   */
-  protected function getInfo() {
-    // Format a message explaining the cells with a red x inside them.
-    $replace = ['@red_dash' => new FormattableMarkup('<span style="color: #ff0000;">-</span>', [])];
-    $message =  $this->t('Cells with a @red_dash indicate that the permission is not available for that role.', $replace);
-
-    // We use FormattableMarkup so the 'style' attribute doesn't get escaped.
-    return ['red_dash_info' => ['#markup' => new FormattableMarkup("<p>$message</p>", [])]];
-  }
-
-  /**
-   * Gets the group type to build the form for.
-   *
-   * @return \Drupal\group\Entity\GroupTypeInterface
-   *   The group type some or more roles belong to.
-   */
-  abstract protected function getGroupType();
-
-  /**
-   * Gets the group roles to display in this form.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface[]
-   *   An array of group role objects.
-   */
-  protected function getGroupRoles() {
-    return [];
-  }
-
-  /**
-   * Gets the permissions to display in this form.
-   *
-   * @return array
-   *   An multidimensional associative array of permissions, keyed by the
-   *   providing module first and then by permission name.
-   */
-  protected function getPermissions() {
-    $permissions_by_provider = [];
-
-    // Create a list of group permissions ordered by their provider.
-    foreach ($this->groupPermissionHandler->getPermissionsByGroupType($this->getGroupType()) as $permission_name => $permission) {
-      $permissions_by_provider[$permission['provider']][$permission_name] = $permission;
-    }
-
-    return $permissions_by_provider;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state) {
-    $role_info = [];
-
-    // Sort the group roles using the static sort() method.
-    // See \Drupal\Core\Config\Entity\ConfigEntityBase::sort().
-    $group_roles = $this->getGroupRoles();
-    uasort($group_roles, '\Drupal\group\Entity\GroupRole::sort');
-
-    // Retrieve information for every role to user further down. We do this to
-    // prevent the same methods from being fired (rows * permissions) times.
-    foreach ($group_roles as $role_name => $group_role) {
-      $role_info[$role_name] = [
-        'label' => $group_role->label(),
-        'permissions' => $group_role->getPermissions(),
-        'is_anonymous' => $group_role->isAnonymous(),
-        'is_outsider' => $group_role->isOutsider(),
-        'is_member' => $group_role->isMember(),
-      ];
-    }
-
-    // Render the general information.
-    if ($info = $this->getInfo()) {
-      $form['info'] = $info;
-    }
-
-    // Render the link for hiding descriptions.
-    $form['system_compact_link'] = [
-      '#id' => FALSE,
-      '#type' => 'system_compact_link',
-    ];
-
-    // Render the roles and permissions table.
-    $form['permissions'] = [
-      '#type' => 'table',
-      '#header' => [$this->t('Permission')],
-      '#id' => 'permissions',
-      '#attributes' => ['class' => ['permissions', 'js-permissions']],
-      '#sticky' => TRUE,
-    ];
-
-    // Create a column with header for every group role.
-    foreach ($role_info as $info) {
-      $form['permissions']['#header'][] = [
-        'data' => $info['label'],
-        'class' => ['checkbox'],
-      ];
-    }
-
-    // Render the permission as sections of rows.
-    $hide_descriptions = system_admin_compact_mode();
-    foreach ($this->getPermissions() as $provider => $permissions) {
-      // Start each section with a full width row containing the provider name.
-      $form['permissions'][$provider] = [[
-        '#wrapper_attributes' => [
-          'colspan' => count($group_roles) + 1,
-          'class' => ['module'],
-          'id' => 'module-' . $provider,
-        ],
-        '#markup' => $this->moduleHandler->getName($provider),
-      ]];
-
-      // Then list all of the permissions for that provider.
-      foreach ($permissions as $perm => $perm_item) {
-        // Create a row for the permission, starting with the description cell.
-        $form['permissions'][$perm]['description'] = [
-          '#type' => 'inline_template',
-          '#template' => '<div class="permission"><span class="title">{{ title }}</span>{% if description or warning %}<div class="description">{% if warning %}<em class="permission-warning">{{ warning }}</em><br />{% endif %}{{ description }}</div>{% endif %}</div>',
-          '#context' => [
-            'title' => $perm_item['title'],
-          ],
-        ];
-
-        // Show the permission description and warning if toggled on.
-        if (!$hide_descriptions) {
-          $form['permissions'][$perm]['description']['#context']['description'] = $perm_item['description'];
-          $form['permissions'][$perm]['description']['#context']['warning'] = $perm_item['warning'];
-        }
-
-        // Finally build a checkbox cell for every group role.
-        foreach ($role_info as $role_name => $info) {
-          // Determine whether the permission is available for this role.
-          $na = $info['is_anonymous'] && !in_array('anonymous', $perm_item['allowed for']);
-          $na = $na || ($info['is_outsider'] && !in_array('outsider', $perm_item['allowed for']));
-          $na = $na || ($info['is_member'] && !in_array('member', $perm_item['allowed for']));
-
-          // Show a red '-' if the permission is unavailable.
-          if ($na) {
-            $form['permissions'][$perm][$role_name] = [
-              '#title' => $info['label'] . ': ' . $perm_item['title'],
-              '#title_display' => 'invisible',
-              '#wrapper_attributes' => [
-                'class' => ['checkbox'],
-                'style' => 'color: #ff0000;',
-              ],
-              '#markup' => '-',
-            ];
-          }
-          // Show a checkbox if the permissions is available.
-          else {
-            $form['permissions'][$perm][$role_name] = [
-              '#title' => $info['label'] . ': ' . $perm_item['title'],
-              '#title_display' => 'invisible',
-              '#wrapper_attributes' => [
-                'class' => ['checkbox'],
-              ],
-              '#type' => 'checkbox',
-              '#default_value' => in_array($perm, $info['permissions']) ? 1 : 0,
-              '#attributes' => ['class' => ['rid-' . $role_name, 'js-rid-' . $role_name]],
-              '#parents' => [$role_name, $perm],
-            ];
-          }
-        }
-      }
-    }
-
-    $form['actions'] = ['#type' => 'actions'];
-    $form['actions']['submit'] = [
-      '#type' => 'submit',
-      '#value' => $this->t('Save permissions'),
-      '#button_type' => 'primary',
-    ];
-
-    // @todo Do something like the global permissions page for 'member'.
-    // $form['#attached']['library'][] = 'user/drupal.user.permissions';
-
-    // Add the CSS from the user module as it has styling for permission tables.
-    $form['#attached']['library'][] = 'user/drupal.user.admin';
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  function submitForm(array &$form, FormStateInterface $form_state) {
-    foreach ($this->getGroupRoles() as $role_name => $group_role) {
-      /** @var \Drupal\group\Entity\GroupRoleInterface $group_role */
-      $permissions = $form_state->getValue($role_name);
-      $group_role->changePermissions($permissions)->trustData()->save();
-    }
-
-    drupal_set_message($this->t('The changes have been saved.'));
-  }
-
-}
diff --git a/web/modules/group/src/Form/GroupPermissionsRoleSpecificForm.php b/web/modules/group/src/Form/GroupPermissionsRoleSpecificForm.php
deleted file mode 100644
index a690c51a28..0000000000
--- a/web/modules/group/src/Form/GroupPermissionsRoleSpecificForm.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-namespace Drupal\group\Form;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\group\Entity\GroupRoleInterface;
-
-/**
- * Provides the user permissions administration form for a specific group role.
- */
-class GroupPermissionsRoleSpecificForm extends GroupPermissionsForm {
-
-  /**
-   * The specific group role for this form.
-   *
-   * @var \Drupal\group\Entity\GroupRoleInterface
-   */
-  protected $groupRole;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getGroupType() {
-    return $this->groupRole->getGroupType();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getGroupRoles() {
-    return [$this->groupRole->id() => $this->groupRole];
-  }
-
-  /**
-   * Form constructor.
-   *
-   * @param array $form
-   *   An associative array containing the structure of the form.
-   * @param \Drupal\Core\Form\FormStateInterface $form_state
-   *   The current state of the form.
-   * @param \Drupal\group\Entity\GroupRoleInterface $group_role
-   *   The group role used for this form.
-   *
-   * @return array
-   *   The form structure.
-   */
-  public function buildForm(array $form, FormStateInterface $form_state, GroupRoleInterface $group_role = NULL) {
-    if ($group_role->isInternal()) {
-      return [
-        '#title' => t('Error'),
-        'description' => [
-          '#prefix' => '<p>',
-          '#suffix' => '</p>',
-          '#markup' => t('Cannot edit an internal group role directly.'),
-        ],
-      ];
-    }
-
-    $this->groupRole = $group_role;
-    return parent::buildForm($form, $form_state);
-  }
-
-}
diff --git a/web/modules/group/src/Form/GroupPermissionsTypeSpecificForm.php b/web/modules/group/src/Form/GroupPermissionsTypeSpecificForm.php
deleted file mode 100644
index aafe321cbf..0000000000
--- a/web/modules/group/src/Form/GroupPermissionsTypeSpecificForm.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-
-namespace Drupal\group\Form;
-
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\group\Access\GroupPermissionHandlerInterface;
-use Drupal\group\Entity\GroupTypeInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides the user permissions administration form for a specific group type.
- */
-class GroupPermissionsTypeSpecificForm extends GroupPermissionsForm {
-
-  /**
-   * The specific group role for this form.
-   *
-   * @var \Drupal\group\Entity\GroupTypeInterface
-   */
-  protected $groupType;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * Constructs a new GroupPermissionsForm.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\group\Access\GroupPermissionHandlerInterface $permission_handler
-   *   The group permission handler.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
-   */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager, GroupPermissionHandlerInterface $permission_handler, ModuleHandlerInterface $module_handler) {
-    parent::__construct($permission_handler, $module_handler);
-    $this->entityTypeManager = $entity_type_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('entity_type.manager'),
-      $container->get('group.permissions'),
-      $container->get('module_handler')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getInfo() {
-    $list = [
-      'role_info' => [
-        '#prefix' => '<p>' . $this->t('Group types use three special roles:') . '</p>',
-        '#theme' => 'item_list',
-        '#items' => [
-          ['#markup' => $this->t('<strong>Anonymous:</strong> This is the same as the global Anonymous role, meaning the user has no account.')],
-          ['#markup' => $this->t('<strong>Outsider:</strong> This means the user has an account on the site, but is not a member of the group.')],
-          ['#markup' => $this->t('<strong>Member:</strong> The default role for anyone in the group. Behaves like the "Authenticated user" role does globally.')],
-        ],
-      ],
-    ];
-
-    return $list + parent::getInfo();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getGroupType() {
-    return $this->groupType;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getGroupRoles() {
-    $properties = [
-      'group_type' => $this->groupType->id(),
-      'permissions_ui' => TRUE,
-    ];
-
-    return $this->entityTypeManager
-      ->getStorage('group_role')
-      ->loadByProperties($properties);
-  }
-
-  /**
-   * Form constructor.
-   *
-   * @param array $form
-   *   An associative array containing the structure of the form.
-   * @param \Drupal\Core\Form\FormStateInterface $form_state
-   *   The current state of the form.
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   The group type used for this form.
-   *
-   * @return array
-   *   The form structure.
-   */
-  public function buildForm(array $form, FormStateInterface $form_state, GroupTypeInterface $group_type = NULL) {
-    $this->groupType = $group_type;
-    return parent::buildForm($form, $form_state);
-  }
-
-}
diff --git a/web/modules/group/src/Form/GroupSettingsForm.php b/web/modules/group/src/Form/GroupSettingsForm.php
deleted file mode 100644
index 68e56fe537..0000000000
--- a/web/modules/group/src/Form/GroupSettingsForm.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-namespace Drupal\group\Form;
-
-use Drupal\Core\Form\ConfigFormBase;
-use Drupal\Core\Form\FormStateInterface;
-
-/**
- * Class GroupSettingsForm.
- */
-class GroupSettingsForm extends ConfigFormBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-    return 'group_settings';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getEditableConfigNames() {
-    return ['group.settings'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state) {
-    $form = parent::buildForm($form, $form_state);
-
-    $config = $this->config('group.settings');
-    $form['use_admin_theme'] = [
-      '#type' => 'checkbox',
-      '#title' => $this->t('Use admin theme'),
-      '#description' => $this->t("Enables the administration theme for editing groups, members, etc."),
-      '#default_value' => $config->get('use_admin_theme'),
-    ];
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-    $config = $this->config('group.settings');
-    $conf_admin_theme = $config->get('use_admin_theme');
-    $form_admin_theme = $form_state->getValue('use_admin_theme');
-
-    // Only rebuild the routes if the admin theme switch has changed.
-    if ($conf_admin_theme != $form_admin_theme) {
-      $config->set('use_admin_theme', $form_admin_theme)->save();
-      \Drupal::service('router.builder')->setRebuildNeeded();
-    }
-
-    parent::submitForm($form, $form_state);
-  }
-
-}
diff --git a/web/modules/group/src/GroupMembership.php b/web/modules/group/src/GroupMembership.php
deleted file mode 100644
index 08c8f26c15..0000000000
--- a/web/modules/group/src/GroupMembership.php
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-
-namespace Drupal\group;
-
-use Drupal\Core\Cache\CacheableDependencyInterface;
-use Drupal\group\Entity\GroupContentInterface;
-
-/**
- * Wrapper class for a GroupContent entity representing a membership.
- * 
- * Should be loaded through the 'group.membership_loader' service.
- */
-class GroupMembership implements CacheableDependencyInterface {
-
-  /**
-   * The group content entity to wrap.
-   *
-   * @var \Drupal\group\Entity\GroupContentInterface
-   */
-  protected $groupContent;
-
-  /**
-   * Constructs a new GroupMembership.
-   *
-   * @param \Drupal\group\Entity\GroupContentInterface $group_content
-   *   The group content entity representing the membership.
-   *
-   * @throws \Exception
-   *   Exception thrown when trying to instantiate this class with a
-   *   GroupContent entity that was not based on the GroupMembership content
-   *   enabler plugin.
-   */
-  public function __construct(GroupContentInterface $group_content) {
-    if ($group_content->getGroupContentType()->getContentPluginId() == 'group_membership') {
-      $this->groupContent = $group_content;
-    }
-    else {
-      throw new \Exception('Trying to create a GroupMembership from an incompatible GroupContent entity.');
-    }
-  }
-
-  /**
-   * Returns the fieldable GroupContent entity for the membership.
-   *
-   * @return \Drupal\group\Entity\GroupContentInterface
-   */
-  public function getGroupContent() {
-    return $this->groupContent;
-  }
-
-  /**
-   * Returns the group for the membership.
-   *
-   * @return \Drupal\group\Entity\GroupInterface
-   */
-  public function getGroup() {
-    return $this->groupContent->getGroup();
-  }
-
-  /**
-   * Returns the user for the membership.
-   *
-   * @return \Drupal\user\UserInterface
-   */
-  public function getUser() {
-    return $this->groupContent->getEntity();
-  }
-
-  /**
-   * Returns the group roles for the membership.
-   *
-   * @return \Drupal\group\Entity\GroupRoleInterface[]
-   *   An array of group roles, keyed by their ID.
-   */
-  public function getRoles() {
-    /** @var \Drupal\group\Entity\Storage\GroupRoleStorageInterface $group_role_storage */
-    $group_role_storage = \Drupal::entityTypeManager()->getStorage('group_role');
-    return $group_role_storage->loadByUserAndGroup($this->getUser(), $this->getGroup());
-  }
-
-  /**
-   * Checks whether the member has a permission.
-   *
-   * @param string $permission
-   *   The permission to check for.
-   *
-   * @return bool
-   *   Whether the member has the requested permission.
-   */
-  public function hasPermission($permission) {
-    foreach ($this->getRoles() as $group_role) {
-      if ($group_role->hasPermission($permission)) {
-        return TRUE;
-      }
-    }
-    return FALSE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheContexts() {
-    return $this->getGroupContent()->getCacheContexts();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheTags() {
-    return $this->getGroupContent()->getCacheTags();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheMaxAge() {
-    return $this->getGroupContent()->getCacheMaxAge();
-  }
-
-}
diff --git a/web/modules/group/src/GroupMembershipLoader.php b/web/modules/group/src/GroupMembershipLoader.php
deleted file mode 100644
index 1feda75109..0000000000
--- a/web/modules/group/src/GroupMembershipLoader.php
+++ /dev/null
@@ -1,125 +0,0 @@
-<?php
-
-namespace Drupal\group;
-
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupInterface;
-
-/**
- * Generates and caches the permissions hash for a group membership.
- */
-class GroupMembershipLoader implements GroupMembershipLoaderInterface {
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The current user's account object.
-   *
-   * @var \Drupal\Core\Session\AccountInterface
-   */
-  protected $currentUser;
-
-  /**
-   * Constructs a new GroupTypeController.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\Core\Session\AccountInterface $current_user
-   *   The current user.
-   */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager, AccountInterface $current_user) {
-    $this->entityTypeManager = $entity_type_manager;
-    $this->currentUser = $current_user;
-  }
-
-  /**
-   * Gets the group content storage.
-   *
-   * @return \Drupal\group\Entity\Storage\GroupContentStorageInterface
-   */
-  protected function groupContentStorage() {
-    return $this->entityTypeManager->getStorage('group_content');
-  }
-
-  /**
-   * Wraps GroupContent entities ina GroupMembership object.
-   *
-   * @param \Drupal\group\Entity\GroupContentInterface[] $entities
-   *   An array of GroupContent entities to wrap.
-   * 
-   * @return \Drupal\group\GroupMembership[]
-   *   A list of GroupMembership wrapper objects.
-   */
-  protected function wrapGroupContentEntities($entities) {
-    $group_memberships = [];
-    foreach ($entities as $group_content) {
-      $group_memberships[] = new GroupMembership($group_content);
-    }
-    return $group_memberships;
-  }
-  
-  /**
-   * {@inheritdoc}
-   */
-  public function load(GroupInterface $group, AccountInterface $account) {
-    $filters = ['entity_id' => $account->id()];
-    $group_contents = $this->groupContentStorage()->loadByGroup($group, 'group_membership', $filters);
-    $group_memberships = $this->wrapGroupContentEntities($group_contents);
-    return $group_memberships ? reset($group_memberships) : FALSE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function loadByGroup(GroupInterface $group, $roles = NULL) {
-    $filters = [];
-    
-    if (isset($roles)) {
-      $filters['group_roles'] = (array) $roles;
-    }
-    
-    $group_contents = $this->groupContentStorage()->loadByGroup($group, 'group_membership', $filters);
-    return $this->wrapGroupContentEntities($group_contents);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function loadByUser(AccountInterface $account = NULL, $roles = NULL) {
-    if (!isset($account)) {
-      $account = $this->currentUser;
-    }
-
-    // Load all group content types for the membership content enabler plugin.
-    $group_content_types = $this->entityTypeManager
-      ->getStorage('group_content_type')
-      ->loadByProperties(['content_plugin' => 'group_membership']);
-
-    // If none were found, there can be no memberships either.
-    if (empty($group_content_types)) {
-      return [];
-    }
-
-    // Try to load all possible membership group content for the user.
-    $group_content_type_ids = [];
-    foreach ($group_content_types as $group_content_type) {
-      $group_content_type_ids[] = $group_content_type->id();
-    }
-
-    $properties = ['type' => $group_content_type_ids, 'entity_id' => $account->id()];
-    if (isset($roles)) {
-      $properties['group_roles'] = (array) $roles;
-    }
-
-    /** @var \Drupal\group\Entity\GroupContentInterface[] $group_contents */
-    $group_contents = $this->groupContentStorage()->loadByProperties($properties);
-    return $this->wrapGroupContentEntities($group_contents);
-  }
-
-}
diff --git a/web/modules/group/src/GroupMembershipLoaderInterface.php b/web/modules/group/src/GroupMembershipLoaderInterface.php
deleted file mode 100644
index 4da40504c9..0000000000
--- a/web/modules/group/src/GroupMembershipLoaderInterface.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-namespace Drupal\group;
-
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupInterface;
-
-/**
- * Defines the group membership loader interface.
- */
-interface GroupMembershipLoaderInterface {
-
-  /**
-   * Loads a membership by group and user.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to load the membership from.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The user to load the membership for.
-   *
-   * @return \Drupal\group\GroupMembership|false
-   *   The loaded GroupMembership or FALSE if none was found.
-   */
-  public function load(GroupInterface $group, AccountInterface $account);
-
-  /**
-   * Loads all memberships for a group.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to load the memberships from.
-   * @param string|array $roles
-   *   (optional) A group role machine name or a list of group role machine
-   *   names to filter on. Valid results only need to match on one role.
-   *
-   * @return \Drupal\group\GroupMembership[]
-   *   The loaded GroupMemberships matching the criteria.
-   */
-  public function loadByGroup(GroupInterface $group, $roles = NULL);
-
-  /**
-   * Loads all memberships for a user.
-   *
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   (optional) The user to load the membership for. Leave blank to load the
-   *   memberships of the currently logged in user.
-   * @param string|array $roles
-   *   (optional) A group role machine name or a list of group role machine
-   *   names to filter on. Valid results only need to match on one role.
-   *
-   * @return \Drupal\group\GroupMembership[]
-   *   The loaded GroupMemberships matching the criteria.
-   */
-  public function loadByUser(AccountInterface $account = NULL, $roles = NULL);
-
-}
diff --git a/web/modules/group/src/Plugin/Block/GroupOperationsBlock.php b/web/modules/group/src/Plugin/Block/GroupOperationsBlock.php
deleted file mode 100644
index ba194520b7..0000000000
--- a/web/modules/group/src/Plugin/Block/GroupOperationsBlock.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\Block;
-
-use Drupal\Core\Block\BlockBase;
-
-/**
- * Provides a block with operations the user can perform on a group.
- *
- * @Block(
- *   id = "group_operations",
- *   admin_label = @Translation("Group operations"),
- *   context = {
- *     "group" = @ContextDefinition("entity:group", required = FALSE)
- *   }
- * )
- */
-class GroupOperationsBlock extends BlockBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function build() {
-    // This block varies per group type and per current user's group membership
-    // permissions. Different group types could have different content plugins
-    // enabled, influencing which group operations are available to them. The
-    // active user's group permissions define which actions are accessible.
-    //
-    // We do not need to specify the current user or group as cache contexts
-    // because, in essence, a group membership is a union of both.
-    $build['#cache']['contexts'] = ['group.type', 'group_membership.roles.permissions'];
-
-    // Of special note is the cache context 'group_membership.audience'. Where
-    // the above cache contexts should suffice if everything is ran through the
-    // permission system, group operations are an exception. Some operations
-    // such as 'join' and 'leave' not only check for a permission, but also the
-    // audience the user belongs to. I.e.: whether they're a 'member', an
-    // 'outsider' or 'anonymous'.
-    $build['#cache']['contexts'][] = 'group_membership.audience';
-
-    /** @var \Drupal\group\Entity\GroupInterface $group */
-    if (($group = $this->getContextValue('group')) && $group->id()) {
-      $links = [];
-
-      // Retrieve the operations from the installed content plugins.
-      foreach ($group->getGroupType()->getInstalledContentPlugins() as $plugin) {
-        /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-        $links += $plugin->getGroupOperations($group);
-      }
-
-      if ($links) {
-        // Allow modules to alter the collection of gathered links.
-        \Drupal::moduleHandler()->alter('group_operations', $links, $group);
-
-        // Sort the operations by weight.
-        uasort($links, '\Drupal\Component\Utility\SortArray::sortByWeightElement');
-
-        // Create an operations element with all of the links.
-        $build['#type'] = 'operations';
-        // @todo We should have operation links provide cacheable metadata that
-        // we could then merge in here.
-        $build['#links'] = $links;
-      }
-    }
-
-    // If no group was found, cache the empty result on the route.
-    return $build;
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/Condition/GroupType.php b/web/modules/group/src/Plugin/Condition/GroupType.php
deleted file mode 100644
index 6df607e05e..0000000000
--- a/web/modules/group/src/Plugin/Condition/GroupType.php
+++ /dev/null
@@ -1,134 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\Condition;
-
-use Drupal\Core\Condition\ConditionPluginBase;
-use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides a 'Group Type' condition.
- *
- * @Condition(
- *   id = "group_type",
- *   label = @Translation("Group type"),
- *   context = {
- *     "group" = @ContextDefinition("entity:group", label = @Translation("Group"))
- *   }
- * )
- *
- */
-class GroupType extends ConditionPluginBase implements ContainerFactoryPluginInterface {
-
-  /**
-   * The entity storage.
-   *
-   * @var \Drupal\Core\Entity\EntityStorageInterface
-   */
-  protected $entityStorage;
-
-  /**
-   * Creates a new GroupType instance.
-   *
-   * @param \Drupal\Core\Entity\EntityStorageInterface $entity_storage
-   *   The entity storage.
-   * @param array $configuration
-   *   The plugin configuration, i.e. an array with configuration values keyed
-   *   by configuration option name. The special key 'context' may be used to
-   *   initialize the defined contexts by setting it to an array of context
-   *   values keyed by context names.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   */
-  public function __construct(EntityStorageInterface $entity_storage, array $configuration, $plugin_id, $plugin_definition) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-    $this->entityStorage = $entity_storage;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $container->get('entity_type.manager')->getStorage('group_type'),
-      $configuration,
-      $plugin_id,
-      $plugin_definition
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
-    $options = [];
-
-    // Build a list of group type labels.
-    $group_types = $this->entityStorage->loadMultiple();
-    foreach ($group_types as $type) {
-      $options[$type->id()] = $type->label();
-    }
-
-    // Show a series of checkboxes for group type selection.
-    $form['group_types'] = [
-      '#title' => $this->t('Group types'),
-      '#type' => 'checkboxes',
-      '#options' => $options,
-      '#default_value' => $this->configuration['group_types'],
-    ];
-
-    return parent::buildConfigurationForm($form, $form_state);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
-    $this->configuration['group_types'] = array_filter($form_state->getValue('group_types'));
-    parent::submitConfigurationForm($form, $form_state);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function summary() {
-    $group_types = $this->configuration['group_types'];
-
-    // Format a pretty string if multiple group types were selected.
-    if (count($group_types) > 1) {
-      $last = array_pop($group_types);
-      $group_types = implode(', ', $group_types);
-      return $this->t('The group type is @group_types or @last', ['@group_types' => $group_types, '@last' => $last]);
-    }
-
-    // If just one was selected, return a simpler string.
-    return $this->t('The group type is @group_type', ['@group_type' => reset($group_types)]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function evaluate() {
-    // If there are no group types selected and the condition is not negated, we
-    // return TRUE because it means all group types are valid.
-    if (empty($this->configuration['group_types']) && !$this->isNegated()) {
-      return TRUE;
-    }
-
-    // Check if the group type of the group context was selected.
-    $group = $this->getContextValue('group');
-    return !empty($this->configuration['group_types'][$group->bundle()]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function defaultConfiguration() {
-    return ['group_types' => []] + parent::defaultConfiguration();
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/EntityReferenceSelection/GroupTypeRoleSelection.php b/web/modules/group/src/Plugin/EntityReferenceSelection/GroupTypeRoleSelection.php
deleted file mode 100644
index 71ad24fd4a..0000000000
--- a/web/modules/group/src/Plugin/EntityReferenceSelection/GroupTypeRoleSelection.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\EntityReferenceSelection;
-
-use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
-
-/**
- * Only shows the group roles which are available for a group type.
- *
- * The only handler setting is 'group_type_id', a required string that points
- * to the ID of the group type for which this handler will be run.
- *
- * @EntityReferenceSelection(
- *   id = "group_type:group_role",
- *   label = @Translation("Group type role selection"),
- *   entity_types = {"group_role"},
- *   group = "group_type",
- *   weight = 0
- * )
- */
-class GroupTypeRoleSelection extends DefaultSelection {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
-    $group_type_id = $this->configuration['handler_settings']['group_type_id'];
-
-    $query = parent::buildEntityQuery($match, $match_operator);
-    $query->condition('group_type', $group_type_id, '=');
-    $query->condition('internal', 0, '=');
-
-    return $query;
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/GroupContentEnabler/GroupMembership.php b/web/modules/group/src/Plugin/GroupContentEnabler/GroupMembership.php
deleted file mode 100644
index d8a5673742..0000000000
--- a/web/modules/group/src/Plugin/GroupContentEnabler/GroupMembership.php
+++ /dev/null
@@ -1,232 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\GroupContentEnabler;
-
-use Drupal\group\Access\GroupAccessResult;
-use Drupal\group\Entity\GroupInterface;
-use Drupal\group\Entity\GroupContentInterface;
-use Drupal\group\Plugin\GroupContentEnablerBase;
-use Drupal\field\Entity\FieldConfig;
-use Drupal\field\Entity\FieldStorageConfig;
-use Drupal\Core\Url;
-use Drupal\Core\Entity\Entity\EntityFormDisplay;
-use Drupal\Core\Entity\Entity\EntityViewDisplay;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Provides a content enabler for users.
- *
- * @GroupContentEnabler(
- *   id = "group_membership",
- *   label = @Translation("Group membership"),
- *   description = @Translation("Adds users to groups as members."),
- *   entity_type_id = "user",
- *   pretty_path_key = "member",
- *   reference_label = @Translation("Username"),
- *   reference_description = @Translation("The name of the user you want to make a member"),
- *   enforced = TRUE
- * )
- */
-class GroupMembership extends GroupContentEnablerBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupOperations(GroupInterface $group) {
-    $account = \Drupal::currentUser();
-    $operations = [];
-
-    if ($group->getMember($account)) {
-      if ($group->hasPermission('leave group', $account)) {
-        $operations['group-leave'] = [
-          'title' => $this->t('Leave group'),
-          'url' => new Url('entity.group.leave', ['group' => $group->id()]),
-          'weight' => 99,
-        ];
-      }
-    }
-    elseif ($group->hasPermission('join group', $account)) {
-      $operations['group-join'] = [
-        'title' => $this->t('Join group'),
-        'url' => new Url('entity.group.join', ['group' => $group->id()]),
-        'weight' => 0,
-      ];
-    }
-
-    return $operations;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getGroupContentPermissions() {
-    $permissions = parent::getGroupContentPermissions();
-    $defaults = ['title_args' => ['%plugin_name' => $this->getLabel()]];
-
-    // Add extra permissions specific to membership group content entities.
-    $permissions['administer members'] = [
-      'title' => '%plugin_name: Administer group members',
-      'restrict access' => TRUE,
-    ] + $defaults;
-
-    $permissions['join group'] = [
-      'title' => '%plugin_name: Join group',
-      'allowed for' => ['outsider'],
-    ] + $defaults;
-
-    $permissions['leave group'] = [
-      'title' => '%plugin_name: Leave group',
-      'allowed for' => ['member'],
-    ] + $defaults;
-
-    // Update the labels of the default permissions.
-    $permissions['view group_membership content']['title'] = '%plugin_name: View individual group members';
-    $permissions['update own group_membership content']['title'] = '%plugin_name: Edit own membership';
-
-    // Only members can update their membership.
-    $permissions['update own group_membership content']['allowed for'] = ['member'];
-
-    // These are handled by 'administer members', 'join group' or 'leave group'.
-    unset($permissions['create group_membership content']);
-    unset($permissions['update any group_membership content']);
-    unset($permissions['delete any group_membership content']);
-    unset($permissions['delete own group_membership content']);
-
-    return $permissions;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function createAccess(GroupInterface $group, AccountInterface $account) {
-    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, 'administer members');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function viewAccess(GroupContentInterface $group_content, AccountInterface $account) {
-    $group = $group_content->getGroup();
-    $permissions = ['view group_membership content', 'administer members'];
-    return GroupAccessResult::allowedIfHasGroupPermissions($group, $account, $permissions, 'OR');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function updateAccess(GroupContentInterface $group_content, AccountInterface $account) {
-    $group = $group_content->getGroup();
-
-    // Allow members to edit their own membership data.
-    if ($group_content->entity_id->entity->id() == $account->id()) {
-      $permissions = ['update own group_membership content', 'administer members'];
-      return GroupAccessResult::allowedIfHasGroupPermissions($group, $account, $permissions, 'OR');
-    }
-
-    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, 'administer members');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function deleteAccess(GroupContentInterface $group_content, AccountInterface $account) {
-    $group = $group_content->getGroup();
-    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, 'administer members');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityReferenceSettings() {
-    $settings = parent::getEntityReferenceSettings();
-    $settings['handler_settings']['include_anonymous'] = FALSE;
-    return $settings;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function postInstall() {
-    $group_content_type_id = $this->getContentTypeConfigId();
-
-    // Add the group_roles field to the newly added group content type. The
-    // field storage for this is defined in the config/install folder. The
-    // default handler for 'group_role' target entities in the 'group_type'
-    // handler group is GroupTypeRoleSelection.
-    FieldConfig::create([
-      'field_storage' => FieldStorageConfig::loadByName('group_content', 'group_roles'),
-      'bundle' => $group_content_type_id,
-      'label' => $this->t('Roles'),
-      'settings' => [
-        'handler' => 'group_type:group_role',
-        'handler_settings' => [
-          'group_type_id' => $this->getGroupTypeId(),
-        ],
-      ],
-    ])->save();
-
-    // Build the 'default' display ID for both the entity form and view mode.
-    $default_display_id = "group_content.$group_content_type_id.default";
-
-    // Build or retrieve the 'default' form mode.
-    if (!$form_display = EntityFormDisplay::load($default_display_id)) {
-      $form_display = EntityFormDisplay::create([
-        'targetEntityType' => 'group_content',
-        'bundle' => $group_content_type_id,
-        'mode' => 'default',
-        'status' => TRUE,
-      ]);
-    }
-
-    // Build or retrieve the 'default' view mode.
-    if (!$view_display = EntityViewDisplay::load($default_display_id)) {
-      $view_display = EntityViewDisplay::create([
-        'targetEntityType' => 'group_content',
-        'bundle' => $group_content_type_id,
-        'mode' => 'default',
-        'status' => TRUE,
-      ]);
-    }
-
-    // Assign widget settings for the 'default' form mode.
-    $form_display->setComponent('group_roles', [
-      'type' => 'options_buttons',
-    ])->save();
-
-    // Assign display settings for the 'default' view mode.
-    $view_display->setComponent('group_roles', [
-      'label' => 'above',
-      'type' => 'entity_reference_label',
-      'settings' => [
-        'link' => 0,
-      ],
-    ])->save();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function defaultConfiguration() {
-    $config = parent::defaultConfiguration();
-    $config['entity_cardinality'] = 1;
-    return $config;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
-    $form = parent::buildConfigurationForm($form, $form_state);
-
-    // Disable the entity cardinality field as the functionality of this module
-    // relies on a cardinality of 1. We don't just hide it, though, to keep a UI
-    // that's consistent with other content enabler plugins.
-    $info = $this->t("This field has been disabled by the plugin to guarantee the functionality that's expected of it.");
-    $form['entity_cardinality']['#disabled'] = TRUE;
-    $form['entity_cardinality']['#description'] .= '<br /><em>' . $info . '</em>';
-
-    return $form;
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/GroupContentEnablerBase.php b/web/modules/group/src/Plugin/GroupContentEnablerBase.php
deleted file mode 100644
index d060971e7c..0000000000
--- a/web/modules/group/src/Plugin/GroupContentEnablerBase.php
+++ /dev/null
@@ -1,552 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin;
-
-use Drupal\Core\Access\AccessResult;
-use Drupal\group\Access\GroupAccessResult;
-use Drupal\group\Entity\GroupType;
-use Drupal\group\Entity\GroupInterface;
-use Drupal\group\Entity\GroupContentInterface;
-use Drupal\Component\Utility\NestedArray;
-use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Plugin\PluginBase;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Provides a base class for GroupContentEnabler plugins.
- *
- * @see \Drupal\group\Annotation\GroupContentEnabler
- * @see \Drupal\group\GroupContentEnablerManager
- * @see \Drupal\group\Plugin\GroupContentEnablerInterface
- * @see plugin_api
- */
-abstract class GroupContentEnablerBase extends PluginBase implements GroupContentEnablerInterface {
-
-  /**
-   * The ID of group type this plugin was instantiated for.
-   *
-   * @var string
-   */
-  protected $groupTypeId;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-
-    // Only support setting the group type ID during construction.
-    if (!empty($configuration['group_type_id'])) {
-      $this->groupTypeId = $configuration['group_type_id'];
-    }
-
-    // Include the default configuration by calling ::setConfiguration().
-    $this->setConfiguration($configuration);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getProvider() {
-    return $this->pluginDefinition['provider'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getLabel() {
-    return $this->pluginDefinition['label'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDescription() {
-    return $this->pluginDefinition['description'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityTypeId() {
-    return $this->pluginDefinition['entity_type_id'];
-  }
-
-  /**
-   * Returns the entity type definition the plugin supports.
-   *
-   * @return \Drupal\Core\Entity\EntityTypeInterface
-   *   The entity type definition.
-   */
-  protected function getEntityType() {
-    return \Drupal::entityTypeManager()->getDefinition($this->getEntityTypeId());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityBundle() {
-    return $this->pluginDefinition['entity_bundle'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupCardinality() {
-    return $this->configuration['group_cardinality'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityCardinality() {
-    return $this->configuration['entity_cardinality'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupType() {
-    if ($id = $this->getGroupTypeId()) {
-      return GroupType::load($id);
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupTypeId() {
-    return $this->groupTypeId;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function definesEntityAccess() {
-    return $this->pluginDefinition['entity_access'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isEnforced() {
-    return $this->pluginDefinition['enforced'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentLabel(GroupContentInterface $group_content) {
-    return $group_content->getEntity()->label();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentTypeConfigId() {
-    $preferred_id = $this->getGroupTypeId() . '-' . str_replace(':', '-', $this->getPluginId());
-
-    // Return a hashed ID if the readable ID would exceed the maximum length.
-    if (strlen($preferred_id) > EntityTypeInterface::BUNDLE_MAX_LENGTH) {
-      $hashed_id = 'group_content_type_' . md5($preferred_id);
-      $preferred_id = substr($hashed_id, 0, EntityTypeInterface::BUNDLE_MAX_LENGTH);
-    }
-
-    return $preferred_id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentTypeLabel() {
-    return $this->getGroupType()->label() . ': ' . $this->getLabel();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContentTypeDescription() {
-    return $this->getDescription();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupOperations(GroupInterface $group) {
-    return [];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getOperations() {
-    return [];
-  }
-
-  /**
-   * Provides permissions for the group content entity; i.e. the relationship.
-   *
-   * @return array
-   *   An array of group permissions, see ::getPermissions for more info.
-   *
-   * @see GroupContentEnablerInterface::getPermissions()
-   */
-  protected function getGroupContentPermissions() {
-    $plugin_id = $this->getPluginId();
-
-    // Allow permissions here and in child classes to easily use the plugin name
-    // and target entity type name in their titles and descriptions.
-    $t_args = [
-      '%plugin_name' => $this->getLabel(),
-      '%entity_type' => $this->getEntityType()->getLowercaseLabel(),
-    ];
-    $defaults = ['title_args' => $t_args, 'description_args' => $t_args];
-
-    // Use the same title prefix to keep permissions sorted properly.
-    $prefix = '%plugin_name - Relationship:';
-
-    $permissions["view $plugin_id content"] = [
-      'title' => "$prefix View entity relations",
-    ] + $defaults;
-
-    $permissions["create $plugin_id content"] = [
-      'title' => "$prefix Add entity relation",
-      'description' => 'Allows you to relate an existing %entity_type entity to the group.',
-    ] + $defaults;
-
-    $permissions["update own $plugin_id content"] = [
-      'title' => "$prefix Edit own entity relations",
-    ] + $defaults;
-
-    $permissions["update any $plugin_id content"] = [
-      'title' => "$prefix Edit any entity relation",
-    ] + $defaults;
-
-    $permissions["delete own $plugin_id content"] = [
-      'title' => "$prefix Delete own entity relations",
-    ] + $defaults;
-
-    $permissions["delete any $plugin_id content"] = [
-      'title' => "$prefix Delete any entity relation",
-    ] + $defaults;
-
-    return $permissions;
-  }
-
-  /**
-   * Provides permissions for the actual entity being added to the group.
-   *
-   * @return array
-   *   An array of group permissions, see ::getPermissions for more info.
-   *
-   * @see GroupContentEnablerInterface::getPermissions()
-   */
-  protected function getTargetEntityPermissions() {
-    $plugin_id = $this->getPluginId();
-
-    // Allow permissions here and in child classes to easily use the plugin and
-    // target entity type labels in their titles and descriptions.
-    $t_args = [
-      '%plugin_name' => $this->getLabel(),
-      '%entity_type' => $this->getEntityType()->getLowercaseLabel(),
-    ];
-    $defaults = ['title_args' => $t_args, 'description_args' => $t_args];
-
-    // Use the same title prefix to keep permissions sorted properly.
-    $prefix = '%plugin_name - Entity:';
-
-    $permissions["view $plugin_id entity"] = [
-      'title' => "$prefix View %entity_type entities",
-    ] + $defaults;
-
-    $permissions["create $plugin_id entity"] = [
-      'title' => "$prefix Add %entity_type entities",
-      'description' => 'Allows you to create a new %entity_type entity and relate it to the group.',
-    ] + $defaults;
-
-    $permissions["update own $plugin_id entity"] = [
-      'title' => "$prefix Edit own %entity_type entities",
-    ] + $defaults;
-
-    $permissions["update any $plugin_id entity"] = [
-      'title' => "$prefix Edit any %entity_type entities",
-    ] + $defaults;
-
-    $permissions["delete own $plugin_id entity"] = [
-      'title' => "$prefix Delete own %entity_type entities",
-    ] + $defaults;
-
-    $permissions["delete any $plugin_id entity"] = [
-      'title' => "$prefix Delete any %entity_type entities",
-    ] + $defaults;
-
-    return $permissions;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPermissions() {
-    $permissions = $this->getGroupContentPermissions();
-    if ($this->definesEntityAccess()) {
-      $permissions += $this->getTargetEntityPermissions();
-    }
-    return $permissions;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function createEntityAccess(GroupInterface $group, AccountInterface $account) {
-    // You cannot create target entities if the plugin does not support it.
-    if (!$this->definesEntityAccess()) {
-      return AccessResult::neutral();
-    }
-
-    $plugin_id = $this->getPluginId();
-    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "create $plugin_id entity");
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function createAccess(GroupInterface $group, AccountInterface $account) {
-    $plugin_id = $this->getPluginId();
-    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "create $plugin_id content");
-  }
-
-  /**
-   * Performs access check for the view operation.
-   *
-   * This method is supposed to be overwritten by extending classes that
-   * do their own custom access checking.
-   *
-   * @param \Drupal\group\Entity\GroupContentInterface $group_content
-   *   The group content for which to check access.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The user for which to check access.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  protected function viewAccess(GroupContentInterface $group_content, AccountInterface $account) {
-    $group = $group_content->getGroup();
-    $plugin_id = $this->getPluginId();
-    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "view $plugin_id content");
-  }
-
-  /**
-   * Performs access check for the update operation.
-   *
-   * This method is supposed to be overwritten by extending classes that
-   * do their own custom access checking.
-   *
-   * @param \Drupal\group\Entity\GroupContentInterface $group_content
-   *   The group content for which to check access.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The user for which to check access.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  protected function updateAccess(GroupContentInterface $group_content, AccountInterface $account) {
-    $group = $group_content->getGroup();
-    $plugin_id = $this->getPluginId();
-
-    // Allow members to edit their own group content.
-    if ($group_content->getOwnerId() == $account->id()) {
-      return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "update own $plugin_id content");
-    }
-
-    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "update any $plugin_id content");
-  }
-
-  /**
-   * Performs access check for the delete operation.
-   *
-   * This method is supposed to be overwritten by extending classes that
-   * do their own custom access checking.
-   *
-   * @param \Drupal\group\Entity\GroupContentInterface $group_content
-   *   The group content for which to check access.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The user for which to check access.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  protected function deleteAccess(GroupContentInterface $group_content, AccountInterface $account) {
-    $group = $group_content->getGroup();
-    $plugin_id = $this->getPluginId();
-
-    // Allow members to delete their own group content.
-    if ($group_content->getOwnerId() == $account->id()) {
-      return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "delete own $plugin_id content");
-    }
-
-    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "delete any $plugin_id content");
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function checkAccess(GroupContentInterface $group_content, $operation, AccountInterface $account) {
-    switch ($operation) {
-      case 'view':
-        $result = $this->viewAccess($group_content, $account);
-        break;
-      case 'update':
-        $result = $this->updateAccess($group_content, $account);
-        break;
-      case 'delete':
-        $result = $this->deleteAccess($group_content, $account);
-        break;
-      default:
-        $result = GroupAccessResult::neutral();
-    }
-
-    return $result;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityReferenceLabel() {
-    return isset($this->pluginDefinition['reference_label'])
-      ? $this->pluginDefinition['reference_label']
-      : NULL;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityReferenceDescription() {
-    return isset($this->pluginDefinition['reference_description'])
-      ? $this->pluginDefinition['reference_description']
-      : NULL;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getEntityReferenceSettings() {
-    $settings['target_type'] = $this->getEntityTypeId();
-    if ($bundle = $this->getEntityBundle()) {
-      $settings['handler_settings']['target_bundles'] = [$bundle];
-    }
-    return $settings;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function postInstall() {
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getConfiguration() {
-    return $this->configuration;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setConfiguration(array $configuration) {
-    // Do not allow the changing of the group type ID after construction.
-    unset($configuration['group_type_id']);
-
-    // Merge in the default configuration.
-    $this->configuration = NestedArray::mergeDeep(
-      $this->defaultConfiguration(),
-      $configuration
-    );
-
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function defaultConfiguration() {
-    // Warning: For every key defined here you need to have a matching config
-    // schema entry following the pattern group_content_enabler.config.MY_KEY!
-    // @see group.schema.yml
-    return [
-      'group_cardinality' => 0,
-      'entity_cardinality' => 0,
-      'use_creation_wizard' => 1
-    ];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
-    /** @var \Drupal\Core\Entity\EntityTypeManager $entity_type_manager */
-    $entity_type_manager = \Drupal::service('entity_type.manager');
-
-    $replace = [
-      '%entity_type' => $entity_type_manager->getDefinition($this->getEntityTypeId())->getLabel(),
-      '%group_type' => $this->getGroupType()->label(),
-      '%plugin' => $this->getLabel(),
-    ];
-
-    $form['group_cardinality'] = [
-      '#type' => 'number',
-      '#title' => $this->t('Group cardinality'),
-      '#description' => $this->t('The amount of %group_type groups a single %entity_type entity can be added to as a %plugin. Set to 0 for unlimited.', $replace),
-      '#default_value' => $this->configuration['group_cardinality'],
-      '#min' => 0,
-      '#required' => TRUE,
-    ];
-
-    $form['entity_cardinality'] = [
-      '#type' => 'number',
-      '#title' => $this->t('Entity cardinality'),
-      '#description' => $this->t('The amount of times a single %entity_type entity can be added to the same %group_type group as a %plugin. Set to 0 for unlimited.', $replace),
-      '#default_value' => $this->configuration['entity_cardinality'],
-      '#min' => 0,
-      '#required' => TRUE,
-    ];
-
-    if ($this->definesEntityAccess()) {
-      $form['use_creation_wizard'] = [
-        '#type' => 'checkbox',
-        '#title' => $this->t('Use 2-step wizard when creating a new %entity_type entity within a %group_type group', $replace),
-        '#description' => $this->t('This will first show you the form to create the actual entity and then a form to create the relationship between the entity and the group.<br />You can choose to disable this wizard if you did not add any fields to the relationship (i.e. this plugin).<br /><strong>Warning:</strong> If you do have fields on the relationship and do not use the wizard, you may end up with required fields not being filled out.', $replace),
-        '#default_value' => $this->configuration['use_creation_wizard'],
-      ];
-    }
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * Only override this function if you need to do something specific to the
-   * submitted data before it is saved as configuration on the plugin. The data
-   * gets saved on the plugin in \Drupal\group\Entity\Form\GroupContentTypeForm.
-   */
-  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function calculateDependencies() {
-    $dependencies['module'][] = $this->getProvider();
-    $dependencies['module'][] = $this->getEntityType()->getProvider();
-    return $dependencies;
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/GroupContentEnablerCollection.php b/web/modules/group/src/Plugin/GroupContentEnablerCollection.php
deleted file mode 100644
index 3e27afeec9..0000000000
--- a/web/modules/group/src/Plugin/GroupContentEnablerCollection.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin;
-
-use Drupal\Core\Plugin\DefaultLazyPluginCollection;
-
-/**
- * A collection of group content plugins.
- */
-class GroupContentEnablerCollection extends DefaultLazyPluginCollection {
-
-  /**
-   * {@inheritdoc}
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerInterface
-   */
-  public function &get($instance_id) {
-    return parent::get($instance_id);
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * Sorts plugins by provider.
-   */
-  public function sortHelper($aID, $bID) {
-    $a = $this->get($aID);
-    $b = $this->get($bID);
-
-    if ($a->getProvider() != $b->getProvider()) {
-      return strnatcasecmp($a->getProvider(), $b->getProvider());
-    }
-
-    return parent::sortHelper($aID, $bID);
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/GroupContentEnablerInterface.php b/web/modules/group/src/Plugin/GroupContentEnablerInterface.php
deleted file mode 100644
index 4c1de0e547..0000000000
--- a/web/modules/group/src/Plugin/GroupContentEnablerInterface.php
+++ /dev/null
@@ -1,297 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin;
-
-use Drupal\Component\Plugin\DerivativeInspectionInterface;
-use Drupal\Component\Plugin\PluginInspectionInterface;
-use Drupal\Component\Plugin\ConfigurablePluginInterface;
-use Drupal\Core\Plugin\PluginFormInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Entity\GroupContentInterface;
-use Drupal\group\Entity\GroupInterface;
-
-/**
- * Defines an interface for pluggable GroupContentEnabler back-ends.
- *
- * @see \Drupal\group\Annotation\GroupContentEnabler
- * @see \Drupal\group\GroupContentEnablerManager
- * @see \Drupal\group\Plugin\GroupContentEnablerBase
- * @see plugin_api
- */
-interface GroupContentEnablerInterface extends PluginInspectionInterface, DerivativeInspectionInterface, ConfigurablePluginInterface, PluginFormInterface {
-
-  /**
-   * Returns the plugin provider.
-   *
-   * @return string
-   */
-  public function getProvider();
-
-  /**
-   * Returns the administrative label for the plugin.
-   *
-   * @return string
-   */
-  public function getLabel();
-
-  /**
-   * Returns the administrative description for the plugin.
-   *
-   * @return string
-   */
-  public function getDescription();
-
-  /**
-   * Returns the entity type ID the plugin supports.
-   *
-   * @return string
-   *   The entity type ID.
-   */
-  public function getEntityTypeId();
-
-  /**
-   * Returns the entity bundle the plugin supports.
-   *
-   * @return string|false
-   *   The bundle name or FALSE in case it supports all bundles.
-   */
-  public function getEntityBundle();
-
-  /**
-   * Returns the amount of groups the same content can be added to.
-   *
-   * @return int
-   *   The group content's group cardinality.
-   */
-  public function getGroupCardinality();
-
-  /**
-   * Returns the amount of times the same content can be added to a group.
-   *
-   * @return int
-   *   The group content's entity cardinality.
-   */
-  public function getEntityCardinality();
-
-  /**
-   * Returns the group type the plugin was instantiated for.
-   *
-   * @return \Drupal\group\Entity\GroupTypeInterface|null
-   *   The group type, if set in the plugin configuration.
-   */
-  public function getGroupType();
-
-  /**
-   * Returns the ID of the group type the plugin was instantiated for.
-   *
-   * @return string|null
-   *   The group type ID, if set in the plugin configuration.
-   */
-  public function getGroupTypeId();
-
-  /**
-   * Returns whether this plugin defines entity access.
-   *
-   * @return bool
-   *   Whether this plugin defines entity access.
-   *
-   * @see \Drupal\group\Annotation\GroupContentEnabler::$entity_access
-   */
-  public function definesEntityAccess();
-
-  /**
-   * Returns whether this plugin is always on.
-   *
-   * @return bool
-   *   The 'enforced' status.
-   */
-  public function isEnforced();
-
-  /**
-   * Retrieves the label for a piece of group content.
-   *
-   * @param \Drupal\group\Entity\GroupContentInterface $group_content
-   *
-   * @return string
-   *   The label as expected by \Drupal\Core\Entity\EntityInterface::label().
-   */
-  public function getContentLabel(GroupContentInterface $group_content);
-
-  /**
-   * Returns a safe, unique configuration ID for a group content type.
-   *
-   * By default we use GROUP_TYPE_ID-PLUGIN_ID-DERIVATIVE_ID, but feel free to
-   * use any other means of identifying group content types.
-   *
-   * Please do not return any invalid characters in the ID as it will crash the
-   * website. Refer to ConfigBase::validateName() for valid characters.
-   *
-   * @return string
-   *   The safe ID to use as the configuration name.
-   *
-   * @see \Drupal\Core\Config\ConfigBase::validateName()
-   */
-  public function getContentTypeConfigId();
-
-  /**
-   * Returns the administrative label for a group content type.
-   *
-   * @return string
-   */
-  public function getContentTypeLabel();
-
-  /**
-   * Returns the administrative description for a group content type.
-   *
-   * @return string
-   */
-  public function getContentTypeDescription();
-
-  /**
-   * Provides a list of operations for a group.
-   *
-   * These operations can be implemented in numerous ways by extending modules.
-   * Out of the box, Group provides a block that shows the available operations
-   * to a user visiting a route with a group in its URL.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to generate the operations for.
-   *
-   * @return array
-   *   An associative array of operation links to show when in a group context,
-   *   keyed by operation name, containing the following key-value pairs:
-   *   - title: The localized title of the operation.
-   *   - url: An instance of \Drupal\Core\Url for the operation URL.
-   *   - weight: The weight of the operation.
-   */
-  public function getGroupOperations(GroupInterface $group);
-
-  /**
-   * Provides a list of operations for the content enabler plugin.
-   *
-   * These operations will be merged with the ones already available on the
-   * group type content configuration page: (un)install, manage fields, etc.
-   *
-   * @return array
-   *   An associative array of operation links to show on the group type content
-   *   administration UI, keyed by operation name, containing the following
-   *   key-value pairs:
-   *   - title: The localized title of the operation.
-   *   - url: An instance of \Drupal\Core\Url for the operation URL.
-   *   - weight: The weight of this operation.
-   */
-  public function getOperations();
-
-  /**
-   * Provides a list of group permissions the plugin exposes.
-   *
-   * If you have some group permissions that would only make sense when your
-   * plugin is installed, you may define those here. They will not be shown on
-   * the permission configuration form unless the plugin is installed.
-   *
-   * @return array
-   *   An array of group permissions, see GroupPermissionHandlerInterface for
-   *   the structure of a group permission.
-   *
-   * @see GroupPermissionHandlerInterface::getPermissions()
-   */
-  public function getPermissions();
-
-  /**
-   * Performs access check for the create target entity operation.
-   *
-   * This method is supposed to be overwritten by extending classes that
-   * do their own custom access checking.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to check for target entity creation access.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The user for which to check access.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function createEntityAccess(GroupInterface $group, AccountInterface $account);
-
-  /**
-   * Performs access check for the create operation.
-   *
-   * This method is supposed to be overwritten by extending classes that
-   * do their own custom access checking.
-   *
-   * @param \Drupal\group\Entity\GroupInterface $group
-   *   The group to check for content creation access.
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The user for which to check access.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function createAccess(GroupInterface $group, AccountInterface $account);
-
-  /**
-   * Checks access to an operation on a given group content entity.
-   *
-   * Use \Drupal\group\Plugin\GroupContentEnablerInterface::createAccess() to
-   * check access to create a group content entity.
-   *
-   * @param \Drupal\group\Entity\GroupContentInterface $group_content
-   *   The group content for which to check access.
-   * @param string $operation
-   *   The operation access should be checked for. Usually one of "view",
-   *   "update" or "delete".
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The user session for which to check access.
-   *
-   * @return \Drupal\Core\Access\AccessResultInterface
-   *   The access result.
-   */
-  public function checkAccess(GroupContentInterface $group_content, $operation, AccountInterface $account);
-
-  /**
-   * Returns the label for the entity reference field.
-   *
-   * This allows you to specify the label for the entity reference field
-   * pointing to the entity that is to become group content.
-   *
-   * @return string|null
-   *   The label for the entity reference field or NULL if none was set.
-   */
-  public function getEntityReferenceLabel();
-
-  /**
-   * Returns the description for the entity reference field.
-   *
-   * This allows you to specify the description for the entity reference field
-   * pointing to the entity that is to become group content.
-   *
-   * @return string|null
-   *   The description for the entity reference field or NULL if none was set.
-   */
-  public function getEntityReferenceDescription();
-
-  /**
-   * Returns a list of entity reference field settings.
-   *
-   * This allows you to provide some handler settings for the entity reference
-   * field pointing to the entity that is to become group content. You could
-   * even change the handler being used, all without having to alter the bundle
-   * field settings yourself through an alter hook.
-   *
-   * @return array
-   *   An associative array where the keys are valid entity reference field
-   *   setting names and the values are the corresponding setting for each key.
-   *   Often used keys are 'target_type', 'handler' and 'handler_settings'.
-   */
-  public function getEntityReferenceSettings();
-
-  /**
-   * Runs tasks after the group content type for this plugin has been created.
-   *
-   * A good example of what you might want to do here, is the installation of
-   * extra locked fields on the group content type. You can find an example in
-   * \Drupal\group\Plugin\GroupContentEnabler\GroupMembership::postInstall().
-   */
-  public function postInstall();
-
-}
diff --git a/web/modules/group/src/Plugin/GroupContentEnablerManager.php b/web/modules/group/src/Plugin/GroupContentEnablerManager.php
deleted file mode 100644
index b2f1e87bac..0000000000
--- a/web/modules/group/src/Plugin/GroupContentEnablerManager.php
+++ /dev/null
@@ -1,421 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin;
-
-use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Plugin\DefaultPluginManager;
-use Drupal\group\Entity\GroupTypeInterface;
-
-/**
- * Manages GroupContentEnabler plugin implementations.
- *
- * @see hook_group_content_info_alter()
- * @see \Drupal\group\Annotation\GroupContentEnabler
- * @see \Drupal\group\Plugin\GroupContentEnablerInterface
- * @see \Drupal\group\Plugin\GroupContentEnablerBase
- * @see plugin_api
- */
-class GroupContentEnablerManager extends DefaultPluginManager implements GroupContentEnablerManagerInterface {
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The group type storage handler.
-   *
-   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
-   */
-  protected $groupTypeStorage;
-
-  /**
-   * A group content type storage handler.
-   *
-   * @var \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface
-   */
-  protected $groupContentTypeStorage;
-
-  /**
-   * A collection of vanilla instances of all content enabler plugins.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerCollection
-   */
-  protected $allPlugins;
-
-  /**
-   * An list each group type's installed plugins as plugin collections.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerCollection[]
-   */
-  protected $groupTypeInstalled = [];
-
-  /**
-   * An static cache of group content type IDs per plugin ID.
-   *
-   * @var array[]
-   */
-  protected $pluginGroupContentTypeMap;
-
-  /**
-   * The cache key for the group content type IDs per plugin ID map.
-   *
-   * @var string
-   */
-  protected $pluginGroupContentTypeMapCacheKey;
-
-  /**
-   * An static cache of plugin IDs per group type ID.
-   *
-   * @var array[]
-   */
-  protected $groupTypePluginMap;
-
-  /**
-   * The cache key for the plugin IDs per group type ID map.
-   *
-   * @var string
-   */
-  protected $groupTypePluginMapCacheKey;
-
-  /**
-   * Constructs a GroupContentEnablerManager object.
-   *
-   * @param \Traversable $namespaces
-   *   An object that implements \Traversable which contains the root paths
-   *   keyed by the corresponding namespace to look for plugin implementations.
-   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
-   *   Cache backend instance to use.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke the alter hook with.
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   */
-  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager) {
-    parent::__construct('Plugin/GroupContentEnabler', $namespaces, $module_handler, 'Drupal\group\Plugin\GroupContentEnablerInterface', 'Drupal\group\Annotation\GroupContentEnabler');
-    $this->alterInfo('group_content_info');
-    $this->setCacheBackend($cache_backend, 'group_content_enablers');
-    $this->entityTypeManager = $entity_type_manager;
-    $this->pluginGroupContentTypeMapCacheKey = $this->cacheKey . '_GCT_map';
-    $this->groupTypePluginMapCacheKey = $this->cacheKey . '_GT_map';
-  }
-
-  /**
-   * Returns the group type storage handler.
-   *
-   * @return \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
-   */
-  protected function getGroupTypeStorage() {
-    if (!isset($this->groupTypeStorage)) {
-      $this->groupTypeStorage = $this->entityTypeManager->getStorage('group_type');
-    }
-    return $this->groupTypeStorage;
-  }
-
-  /**
-   * Returns the group content type storage handler.
-   *
-   * @return \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface
-   */
-  protected function getGroupContentTypeStorage() {
-    if (!isset($this->groupContentTypeStorage)) {
-      $this->groupContentTypeStorage = $this->entityTypeManager->getStorage('group_content_type');
-    }
-    return $this->groupContentTypeStorage;
-  }
-  
-  /**
-   * {@inheritdoc}
-   */
-  public function getAll() {
-    if (!isset($this->allPlugins)) {
-      $collection = new GroupContentEnablerCollection($this, []);
-
-      // Add every known plugin to the collection with a vanilla configuration.
-      foreach ($this->getDefinitions() as $plugin_id => $plugin_info) {
-        $collection->setInstanceConfiguration($plugin_id, ['id' => $plugin_id]);
-      }
-
-      // Sort and set the plugin collection.
-      $this->allPlugins = $collection->sort();
-    }
-
-    return $this->allPlugins;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getInstalled(GroupTypeInterface $group_type = NULL) {
-    return !isset($group_type)
-      ? $this->getVanillaInstalled()
-      : $this->getGroupTypeInstalled($group_type);
-  }
-
-  /**
-   * Retrieves a vanilla instance of every installed plugin.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerCollection
-   *   A plugin collection with a vanilla instance of every installed plugin.
-   */
-  protected function getVanillaInstalled() {
-    // Retrieve a vanilla instance of all known content enabler plugins.
-    $plugins = clone $this->getAll();
-
-    // Retrieve all installed content enabler plugin IDs.
-    $installed = $this->getInstalledIds();
-
-    // Remove uninstalled plugins from the collection.
-    /** @var \Drupal\group\Plugin\GroupContentEnablerCollection $plugins */
-    foreach ($plugins as $plugin_id => $plugin) {
-      if (!in_array($plugin_id, $installed)) {
-        $plugins->removeInstanceId($plugin_id);
-      }
-    }
-
-    return $plugins;
-  }
-
-  /**
-   * Retrieves fully instantiated plugins for a group type.
-   *
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   The group type to instantiate the installed plugins for.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerCollection
-   *   A plugin collection with fully instantiated plugins for the group type.
-   */
-  protected function getGroupTypeInstalled(GroupTypeInterface $group_type) {
-    if (!isset($this->groupTypeInstalled[$group_type->id()])) {
-      $configurations = [];
-      $group_content_types = $this->getGroupContentTypeStorage()->loadByGroupType($group_type);
-
-      // Get the plugin config from every group content type for the group type.
-      foreach ($group_content_types as $group_content_type) {
-        $plugin_id = $group_content_type->getContentPluginId();
-
-        // Grab the plugin config from every group content type and amend it
-        // with the group type ID so the plugin knows what group type to use. We
-        // also specify the 'id' key because DefaultLazyPluginCollection throws
-        // an exception if it is not present.
-        $configuration = $group_content_type->get('plugin_config');
-        $configuration['group_type_id'] = $group_type->id();
-        $configuration['id'] = $plugin_id;
-
-        $configurations[$plugin_id] = $configuration;
-      }
-
-      $plugins = new GroupContentEnablerCollection($this, $configurations);
-      $plugins->sort();
-
-      $this->groupTypeInstalled[$group_type->id()] = $plugins;
-    }
-
-    return $this->groupTypeInstalled[$group_type->id()];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getInstalledIds(GroupTypeInterface $group_type = NULL) {
-    // If no group type was provided, we can find all installed plugin IDs by
-    // grabbing the keys from the group content type IDs per plugin ID map.
-    if (!isset($group_type)) {
-      return array_keys($this->getPluginGroupContentTypeMap());
-    }
-
-    // Otherwise, we can find the entry in the plugin IDs per group type ID map.
-    $map = $this->getGroupTypePluginMap();
-    return isset($map[$group_type->id()]) ? $map[$group_type->id()] : [];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function clearCachedInstalledIds() {
-    $this->clearCachedPluginMaps();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function installEnforced(GroupTypeInterface $group_type = NULL) {
-    $enforced = [];
-
-    // Gather the ID of all plugins that are marked as enforced.
-    foreach ($this->getDefinitions() as $plugin_id => $plugin_info) {
-      if ($plugin_info['enforced']) {
-        $enforced[] = $plugin_id;
-      }
-    }
-
-    // If no group type was specified, we check all of them.
-    /** @var \Drupal\group\Entity\GroupTypeInterface[] $group_types */
-    $group_types = empty($group_type) ? $this->getGroupTypeStorage()->loadMultiple() : [$group_type];
-
-    // Search through all of the enforced plugins and install new ones.
-    foreach ($group_types as $group_type) {
-      $installed = $this->getInstalledIds($group_type);
-
-      foreach ($enforced as $plugin_id) {
-        if (!in_array($plugin_id, $installed)) {
-          $this->getGroupContentTypeStorage()->createFromPlugin($group_type, $plugin_id)->save();
-        }
-      }
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupContentTypeIds($plugin_id) {
-    $map = $this->getPluginGroupContentTypeMap();
-    return isset($map[$plugin_id]) ? $map[$plugin_id] : [];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPluginGroupContentTypeMap() {
-    $map = $this->getCachedPluginGroupContentTypeMap();
-
-    if (!isset($map)) {
-      $map = [];
-
-      /** @var \Drupal\group\Entity\GroupContentTypeInterface[] $group_content_types */
-      $group_content_types = $this->getGroupContentTypeStorage()->loadMultiple();
-      foreach ($group_content_types as $group_content_type) {
-        $map[$group_content_type->getContentPluginId()][] = $group_content_type->id();
-      }
-
-      $this->setCachedPluginGroupContentTypeMap($map);
-    }
-
-    return $map;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function clearCachedGroupContentTypeIdMap() {
-    $this->clearCachedPluginMaps();
-  }
-
-  /**
-   * Returns the cached group content type ID map.
-   *
-   * @return array|null
-   *   On success this will return the group content ID map (array). On failure
-   *   this should return NULL, indicating to other methods that this has not
-   *   yet been defined. Success with no values should return as an empty array.
-   */
-  protected function getCachedPluginGroupContentTypeMap() {
-    if (!isset($this->pluginGroupContentTypeMap) && $cache = $this->cacheGet($this->pluginGroupContentTypeMapCacheKey)) {
-      $this->pluginGroupContentTypeMap = $cache->data;
-    }
-    return $this->pluginGroupContentTypeMap;
-  }
-
-  /**
-   * Sets a cache of the group content type ID map.
-   *
-   * @param array $map
-   *   The group content type ID map to store in cache.
-   */
-  protected function setCachedPluginGroupContentTypeMap($map) {
-    $this->cacheSet($this->pluginGroupContentTypeMapCacheKey, $map, Cache::PERMANENT);
-    $this->pluginGroupContentTypeMap = $map;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getGroupTypePluginMap() {
-    $map = $this->getCachedGroupTypePluginMap();
-
-    if (!isset($map)) {
-      $map = [];
-
-      /** @var \Drupal\group\Entity\GroupContentTypeInterface[] $group_content_types */
-      $group_content_types = $this->getGroupContentTypeStorage()->loadMultiple();
-      foreach ($group_content_types as $group_content_type) {
-        $map[$group_content_type->getGroupTypeId()][] = $group_content_type->getContentPluginId();
-      }
-
-      $this->setCachedGroupTypePluginMap($map);
-    }
-
-    return $map;
-  }
-
-  /**
-   * Returns the cached group type plugin map.
-   *
-   * @return array|null
-   *   On success this will return the group type plugin map (array). On failure
-   *   this should return NULL, indicating to other methods that this has not
-   *   yet been defined. Success with no values should return as an empty array.
-   */
-  protected function getCachedGroupTypePluginMap() {
-    if (!isset($this->groupTypePluginMap) && $cache = $this->cacheGet($this->groupTypePluginMapCacheKey)) {
-      $this->groupTypePluginMap = $cache->data;
-    }
-    return $this->groupTypePluginMap;
-  }
-
-  /**
-   * Sets a cache of the group type plugin map.
-   *
-   * @param array $map
-   *   The group type plugin map to store in cache.
-   */
-  protected function setCachedGroupTypePluginMap($map) {
-    $this->cacheSet($this->groupTypePluginMapCacheKey, $map, Cache::PERMANENT);
-    $this->groupTypePluginMap = $map;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function clearCachedGroupTypeCollections(GroupTypeInterface $group_type = NULL) {
-    if (!isset($group_type)) {
-      $this->groupTypeInstalled = [];
-    }
-    else {
-      $this->groupTypeInstalled[$group_type->id()] = NULL;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function clearCachedPluginMaps() {
-    if ($this->cacheBackend) {
-      $this->cacheBackend->delete($this->pluginGroupContentTypeMapCacheKey);
-      $this->cacheBackend->delete($this->groupTypePluginMapCacheKey);
-    }
-    $this->pluginGroupContentTypeMap = NULL;
-    $this->groupTypePluginMap = NULL;
-
-    // Also clear the array of per group type plugin collections as it shares
-    // its cache clearing requirements with the group type plugin map.
-    $this->groupTypeInstalled = [];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function clearCachedDefinitions() {
-    parent::clearCachedDefinitions();
-
-    // The collection of all plugins should only change if the plugin
-    // definitions change, so we can safely reset that here.
-    $this->allPlugins = NULL;
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/GroupContentEnablerManagerInterface.php b/web/modules/group/src/Plugin/GroupContentEnablerManagerInterface.php
deleted file mode 100644
index f9f1747d95..0000000000
--- a/web/modules/group/src/Plugin/GroupContentEnablerManagerInterface.php
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin;
-
-use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
-use Drupal\Component\Plugin\PluginManagerInterface;
-use Drupal\group\Entity\GroupTypeInterface;
-
-/**
- * Provides a common interface for group content enabler managers.
- */
-interface GroupContentEnablerManagerInterface extends PluginManagerInterface, CachedDiscoveryInterface {
-
-  /**
-   * Returns a plugin collection of all available content enablers.
-   *
-   * This collection will not have anything set in the individual plugins'
-   * configuration. Do not use any methods on the plugin that require a group
-   * type to be set or you may encounter unexpected behavior. Instead, use
-   * ::getInstalled() while providing a group type argument to get fully
-   * configured instances of the plugins.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerCollection
-   *   A plugin collection with a vanilla instance of every known plugin.
-   */
-  public function getAll();
-
-  /**
-   * Returns a plugin collection of all installed content enablers.
-   *
-   * Warning: When called without a $group_type argument, this will return a
-   * collection of vanilla plugin instances. See ::getAll() for details about
-   * vanilla instances.
-   *
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   (optional) The group type to retrieve installed plugin for.
-   *
-   * @return \Drupal\group\Plugin\GroupContentEnablerCollection
-   *   A plugin collection with a vanilla instance of every installed plugin. If
-   *   $group_type was provided, the collection will contain fully instantiated
-   *   plugins for the provided group type.
-   */
-  public function getInstalled(GroupTypeInterface $group_type = NULL);
-
-  /**
-   * Returns the plugin ID of all content enablers in use.
-   *
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   (optional) The group type to retrieve plugin IDs for.
-   *
-   * @return string[]
-   *   A list of all installed content enabler plugin IDs. If $group_type was
-   *   provided, this will only return the installed IDs for that group type.
-   */
-  public function getInstalledIds(GroupTypeInterface $group_type = NULL);
-  
-  /**
-   * Clears static and persistent installed plugin ID caches.
-   * 
-   * @deprecated in Group 1.0-beta3, will be removed before Group 1.0-rc1. Use
-   *   ::clearCachedPluginMaps() instead.
-   */
-  public function clearCachedInstalledIds();
-
-  /**
-   * Installs all plugins which are marked as enforced.
-   *
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   (optional) The group type to install enforced plugins on. Leave blank to
-   *   run the installation process for all group types.
-   */
-  public function installEnforced(GroupTypeInterface $group_type = NULL);
-
-  /**
-   * Retrieves all of the group content type IDs for a content plugin.
-   *
-   * @param $plugin_id
-   *   The ID of the plugin to retrieve group content type IDs for.
-   *
-   * @return string[]
-   *   An array of group content type IDs.
-   */
-  public function getGroupContentTypeIds($plugin_id);
-
-  /**
-   * Retrieves a list of group content type IDs per plugin ID.
-   *
-   * @return array
-   *   An array of group content type ID arrays, keyed by plugin ID.
-   */
-  public function getPluginGroupContentTypeMap();
-
-  /**
-   * Clears static and persistent group content type ID map caches.
-   * 
-   * @deprecated in Group 1.0-beta3, will be removed before Group 1.0-rc1. Use
-   *   ::clearCachedPluginMaps() instead.
-   */
-  public function clearCachedGroupContentTypeIdMap();
-
-  /**
-   * Retrieves a list of plugin IDs per group type ID.
-   *
-   * @return array
-   *   An array of content plugin ID arrays, keyed by group type ID.
-   */
-  public function getGroupTypePluginMap();
-
-  /**
-   * Clears the static per group type plugin collection cache.
-   * 
-   * @param \Drupal\group\Entity\GroupTypeInterface $group_type
-   *   (optional) The group type to clear the cache for. Leave blank to clear
-   *   the cache for all group types.
-   */
-  public function clearCachedGroupTypeCollections(GroupTypeInterface $group_type = NULL);
-  
-  /**
-   * Clears static and persistent plugin ID map caches.
-   */
-  public function clearCachedPluginMaps();
-
-}
diff --git a/web/modules/group/src/Plugin/Menu/LocalAction/WithDestination.php b/web/modules/group/src/Plugin/Menu/LocalAction/WithDestination.php
deleted file mode 100644
index e2e7b39179..0000000000
--- a/web/modules/group/src/Plugin/Menu/LocalAction/WithDestination.php
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\Menu\LocalAction;
-
-use Drupal\Core\Menu\LocalActionDefault;
-use Drupal\Core\Routing\RedirectDestinationInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Routing\RouteProviderInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Modifies the local action to add a destination.
- * 
- * Will either append the already present destination parameter or use the
- * current route's path as the destination parameter.
- * 
- * @todo Follow up on https://www.drupal.org/node/2762131.
- */
-class WithDestination extends LocalActionDefault {
-
-  /**
-   * The redirect destination.
-   *
-   * @var \Drupal\Core\Routing\RedirectDestinationInterface
-   */
-  private $redirectDestination;
-
-  /**
-   * Constructs a WithDestination object.
-   *
-   * @param array $configuration
-   *   A configuration array containing information about the plugin instance.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
-   *   The route provider to load routes by name.
-   * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
-   *   The redirect destination.
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, RedirectDestinationInterface $redirect_destination) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition, $route_provider);
-    $this->redirectDestination = $redirect_destination;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('router.route_provider'),
-      $container->get('redirect.destination')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getOptions(RouteMatchInterface $route_match) {
-    $options = parent::getOptions($route_match);
-    $options['query']['destination'] = $this->redirectDestination->get();
-    return $options;
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/Validation/Constraint/GroupContentCardinality.php b/web/modules/group/src/Plugin/Validation/Constraint/GroupContentCardinality.php
deleted file mode 100644
index edde701cf5..0000000000
--- a/web/modules/group/src/Plugin/Validation/Constraint/GroupContentCardinality.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\Validation\Constraint;
-
-use Symfony\Component\Validator\Constraint;
-
-/**
- * Checks the cardinality limits for a piece of group content.
- *
- * Content enabler plugins may limit the amount of times a single content entity
- * can be added to a group as well as the amount of groups that single entity
- * can be added to. This constraint will enforce that behavior.
- *
- * @Constraint(
- *   id = "GroupContentCardinality",
- *   label = @Translation("Group content cardinality check", context = "Validation"),
- *   type = "entity:group_content"
- * )
- */
-class GroupContentCardinality extends Constraint {
-
-  /**
-   * The message to show when an entity has reached the group cardinality.
-   *
-   * @var string
-   */
-  public $groupMessage = '@field: %content has reached the maximum amount of groups it can be added to';
-
-  /**
-   * The message to show when an entity has reached the entity cardinality.
-   *
-   * @var string
-   */
-  public $entityMessage = '@field: %content has reached the maximum amount of times it can be added to %group';
-
-}
diff --git a/web/modules/group/src/Plugin/Validation/Constraint/GroupContentCardinalityValidator.php b/web/modules/group/src/Plugin/Validation/Constraint/GroupContentCardinalityValidator.php
deleted file mode 100644
index db72a98d6b..0000000000
--- a/web/modules/group/src/Plugin/Validation/Constraint/GroupContentCardinalityValidator.php
+++ /dev/null
@@ -1,143 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\Validation\Constraint;
-
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\Validator\Constraint;
-use Symfony\Component\Validator\ConstraintValidator;
-
-/**
- * Checks the amount of times a single content entity can be added to a group.
- */
-class GroupContentCardinalityValidator extends ConstraintValidator implements ContainerInjectionInterface {
-
-  /**
-   * Type-hinting in parent Symfony class is off, let's fix that.
-   *
-   * @var \Symfony\Component\Validator\Context\ExecutionContextInterface
-   */
-  protected $context;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * Constructs a GroupContentCardinalityValidator object.
-   *
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
-   *   The entity type manager.
-   */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
-    $this->entityTypeManager = $entity_type_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('entity_type.manager')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validate($group_content, Constraint $constraint) {
-    /** @var \Drupal\group\Entity\GroupContentInterface $group_content */
-    /** @var \Drupal\group\Plugin\Validation\Constraint\GroupContentCardinality $constraint */
-    if (!isset($group_content)) {
-      return;
-    }
-
-    // Get the plugin for the group content entity.
-    $plugin = $group_content->getContentPlugin();
-
-    // Get the cardinality settings from the plugin.
-    $group_cardinality = $plugin->getGroupCardinality();
-    $entity_cardinality = $plugin->getEntityCardinality();
-
-    // Exit early if both cardinalities are set to unlimited.
-    if ($group_cardinality <= 0 && $entity_cardinality <= 0) {
-      return;
-    }
-
-    // Only run our checks if an entity was referenced.
-    if ($entity = $group_content->getEntity()) {
-      // Get the entity_id field label for error messages.
-      $field_name = $group_content->getFieldDefinition('entity_id')->getLabel();
-
-      // Enforce the group cardinality if it's not set to unlimited.
-      if ($group_cardinality > 0) {
-        // Get the group content entities for this piece of content.
-        $properties = ['type' => $plugin->getContentTypeConfigId(), 'entity_id' => $entity->id()];
-        $group_instances = $this->entityTypeManager
-          ->getStorage('group_content')
-          ->loadByProperties($properties);
-
-        // Get the groups this content entity already belongs to, not counting
-        // the current group towards the limit.
-        $group_ids = [];
-        foreach ($group_instances as $instance) {
-          /** @var \Drupal\group\Entity\GroupContentInterface $instance */
-          if ($instance->getGroup()->id() != $group_content->getGroup()->id()) {
-            $group_ids[] = $instance->getGroup()->id();
-          }
-        }
-        $group_count = count(array_unique($group_ids));
-
-        // Raise a violation if the content has reached the cardinality limit.
-        if ($group_count >= $group_cardinality) {
-          $this->context->buildViolation($constraint->groupMessage)
-            ->setParameter('@field', $field_name)
-            ->setParameter('%content', $entity->label())
-            // We manually flag the entity reference field as the source of the
-            // violation so form API will add a visual indicator of where the
-            // validation failed.
-            ->atPath('entity_id.0')
-            ->addViolation();
-        }
-      }
-
-      // Enforce the entity cardinality if it's not set to unlimited.
-      if ($entity_cardinality > 0) {
-        $group = $group_content->getGroup();
-
-        // Get the current instances of this content entity in the group.
-        $entity_instances = $group->getContentByEntityId($plugin->getPluginId(), $entity->id());
-        $entity_count = count($entity_instances);
-
-        // If the current group content entity has an ID, exclude that one.
-        if ($group_content_id = $group_content->id()) {
-          foreach ($entity_instances as $instance) {
-            /** @var \Drupal\group\Entity\GroupContentInterface $instance */
-            if ($instance->id() == $group_content_id) {
-              $entity_count--;
-              break;
-            }
-          }
-        }
-
-        // Raise a violation if the content has reached the cardinality limit.
-        if ($entity_count >= $entity_cardinality) {
-          $this->context->buildViolation($constraint->entityMessage)
-            ->setParameter('@field', $field_name)
-            ->setParameter('%content', $entity->label())
-            ->setParameter('%group', $group->label())
-            // We manually flag the entity reference field as the source of the
-            // violation so form API will add a visual indicator of where the
-            // validation failed.
-            ->atPath('entity_id.0')
-            ->addViolation();
-        }
-      }
-    }
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/views/access/GroupPermission.php b/web/modules/group/src/Plugin/views/access/GroupPermission.php
deleted file mode 100644
index 100035b0f0..0000000000
--- a/web/modules/group/src/Plugin/views/access/GroupPermission.php
+++ /dev/null
@@ -1,180 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\views\access;
-
-use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheableDependencyInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Plugin\Context\ContextProviderInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\group\Access\GroupPermissionHandlerInterface;
-use Drupal\views\Plugin\views\access\AccessPluginBase;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\Routing\Route;
-
-/**
- * Access plugin that provides group permission-based access control.
- *
- * @ingroup views_access_plugins
- *
- * @ViewsAccess(
- *   id = "group_permission",
- *   title = @Translation("Group permission"),
- *   help = @Translation("Access will be granted to users with the specified group permission string.")
- * )
- */
-class GroupPermission extends AccessPluginBase implements CacheableDependencyInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected $usesOptions = TRUE;
-
-  /**
-   * The group permission handler.
-   *
-   * @var \Drupal\group\Access\GroupPermissionHandlerInterface
-   */
-  protected $permissionHandler;
-
-  /**
-   * The module handler.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
-   * The group entity from the route.
-   *
-   * @var \Drupal\group\Entity\GroupInterface
-   */
-  protected $group;
-
-  /**
-   * Constructs a Permission object.
-   *
-   * @param array $configuration
-   *   A configuration array containing information about the plugin instance.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   * @param \Drupal\group\Access\GroupPermissionHandlerInterface $permission_handler
-   *   The group permission handler.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
-   * @param \Drupal\Core\Plugin\Context\ContextProviderInterface $context_provider
-   *   The group route context.
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, GroupPermissionHandlerInterface $permission_handler, ModuleHandlerInterface $module_handler, ContextProviderInterface $context_provider) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-    $this->permissionHandler = $permission_handler;
-    $this->moduleHandler = $module_handler;
-
-    /** @var \Drupal\Core\Plugin\Context\ContextInterface[] $contexts */
-    $contexts = $context_provider->getRuntimeContexts(['group']);
-    $this->group = $contexts['group']->getContextValue();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('group.permissions'),
-      $container->get('module_handler'),
-      $container->get('group.group_route_context')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function access(AccountInterface $account) {
-    if (!empty($this->group)) {
-      return $this->group->hasPermission($this->options['group_permission'], $account);
-    }
-    return FALSE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function alterRouteDefinition(Route $route) {
-    $route->setRequirement('_group_permission', $this->options['group_permission']);
-
-    // Upcast any %group path key the user may have configured so the
-    // '_group_permission' access check will receive a properly loaded group.
-    $route->setOption('parameters', ['group' => ['type' => 'entity:group']]);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function summaryTitle() {
-    $permissions = $this->permissionHandler->getPermissions(TRUE);
-    if (isset($permissions[$this->options['group_permission']])) {
-      return $permissions[$this->options['group_permission']]['title'];
-    }
-
-    return $this->t($this->options['group_permission']);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function defineOptions() {
-    $options = parent::defineOptions();
-    $options['group_permission'] = array('default' => 'view group');
-    return $options;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
-    parent::buildOptionsForm($form, $form_state);
-
-    // Get list of permissions
-    $permissions = [];
-    foreach ($this->permissionHandler->getPermissions(TRUE) as $permission_name => $permission) {
-      $display_name = $this->moduleHandler->getName($permission['provider']);
-      $permissions[$display_name][$permission_name] = strip_tags($permission['title']);
-    }
-
-    $form['group_permission'] = array(
-      '#type' => 'select',
-      '#options' => $permissions,
-      '#title' => $this->t('Group permission'),
-      '#default_value' => $this->options['group_permission'],
-      '#description' => $this->t('Only users with the selected group permission will be able to access this display.<br /><strong>Warning:</strong> This will only work if there is a {group} parameter in the route. If not, it will always deny access.'),
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheMaxAge() {
-    return Cache::PERMANENT;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheContexts() {
-    return ['group_membership.roles.permissions'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheTags() {
-    return [];
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/views/argument/GroupId.php b/web/modules/group/src/Plugin/views/argument/GroupId.php
deleted file mode 100644
index 6b1ce67f54..0000000000
--- a/web/modules/group/src/Plugin/views/argument/GroupId.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\views\argument;
-
-use Drupal\Core\Entity\ContentEntityStorageInterface;
-use Drupal\views\Plugin\views\argument\NumericArgument;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Argument handler to accept a group ID.
- *
- * @ViewsArgument("group_id")
- */
-class GroupId extends NumericArgument {
-
-  /**
-   * The group storage.
-   *
-   * @var \Drupal\Core\Entity\ContentEntityStorageInterface
-   */
-  protected $groupStorage;
-
-  /**
-   * Constructs the Gid object.
-   *
-   * @param array $configuration
-   *   A configuration array containing information about the plugin instance.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   * @param ContentEntityStorageInterface $group_storage
-   *   The group entity storage handler.
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, ContentEntityStorageInterface $group_storage) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-    $this->groupStorage = $group_storage;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('entity_type.manager')->getStorage('group')
-    );
-  }
-
-  /**
-   * Override the behavior of title(). Get the title of the group.
-   */
-  public function titleQuery() {
-    $titles = array();
-
-    $groups = $this->groupStorage->loadMultiple($this->value);
-    foreach ($groups as $group) {
-      $titles[] = $group->label();
-    }
-
-    return $titles;
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/views/argument_default/GroupIdFromUrl.php b/web/modules/group/src/Plugin/views/argument_default/GroupIdFromUrl.php
deleted file mode 100644
index ea6c77ddd9..0000000000
--- a/web/modules/group/src/Plugin/views/argument_default/GroupIdFromUrl.php
+++ /dev/null
@@ -1,86 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\views\argument_default;
-
-use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheableDependencyInterface;
-use Drupal\Core\Plugin\Context\ContextProviderInterface;
-use Drupal\views\Plugin\views\argument_default\ArgumentDefaultPluginBase;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Default argument plugin to extract a group ID.
- *
- * @ViewsArgumentDefault(
- *   id = "group_id_from_url",
- *   title = @Translation("Group ID from URL")
- * )
- */
-class GroupIdFromUrl extends ArgumentDefaultPluginBase implements CacheableDependencyInterface {
-
-  /**
-   * The group entity from the route.
-   *
-   * @var \Drupal\group\Entity\GroupInterface
-   */
-  protected $group;
-
-  /**
-   * Constructs a new GroupIdFromUrl instance.
-   *
-   * @param array $configuration
-   *   A configuration array containing information about the plugin instance.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   * @param \Drupal\Core\Plugin\Context\ContextProviderInterface $context_provider
-   *   The group route context.
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, ContextProviderInterface $context_provider) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-
-    /** @var \Drupal\Core\Plugin\Context\ContextInterface[] $contexts */
-    $contexts = $context_provider->getRuntimeContexts(['group']);
-    $this->group = $contexts['group']->getContextValue();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('group.group_route_context')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getArgument() {
-    if (!empty($this->group) && $id = $this->group->id()) {
-      return $id;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheMaxAge() {
-    return Cache::PERMANENT;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheContexts() {
-    // We cache the result on the route instead of the URL so that path aliases
-    // can all use the same cache context. If you look at ::getArgument() you'll
-    // see that we actually get the group ID from the route, not the URL.
-    return ['route'];
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/views/relationship/GroupContentToEntity.php b/web/modules/group/src/Plugin/views/relationship/GroupContentToEntity.php
deleted file mode 100644
index 1cfeec97cb..0000000000
--- a/web/modules/group/src/Plugin/views/relationship/GroupContentToEntity.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\views\relationship;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\group\Entity\GroupContentType;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Drupal\views\Plugin\views\relationship\RelationshipPluginBase;
-use Drupal\views\Plugin\ViewsHandlerManager;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * A relationship handler for group content entity references.
- *
- * Definition items:
- * - target_entity_type: The ID of the entity type this relationship maps to.
- *
- * @ingroup views_relationship_handlers
- *
- * @ViewsRelationship("group_content_to_entity")
- */
-class GroupContentToEntity extends GroupContentToEntityBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getTargetEntityType() {
-    return $this->definition['target_entity_type'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getJoinFieldType() {
-    return 'left_field';
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/views/relationship/GroupContentToEntityBase.php b/web/modules/group/src/Plugin/views/relationship/GroupContentToEntityBase.php
deleted file mode 100644
index 63dea76fd2..0000000000
--- a/web/modules/group/src/Plugin/views/relationship/GroupContentToEntityBase.php
+++ /dev/null
@@ -1,196 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\views\relationship;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\group\Entity\GroupContentType;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Drupal\views\Plugin\views\relationship\RelationshipPluginBase;
-use Drupal\views\Plugin\ViewsHandlerManager;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * A relationship handler base for group content entity references.
- */
-abstract class GroupContentToEntityBase extends RelationshipPluginBase {
-
-  /**
-   * The Views join plugin manager.
-   *
-   * @var \Drupal\views\Plugin\ViewsHandlerManager
-   */
-  protected $joinManager;
-
-  /**
-   * The group content enabler plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * Constructs an GroupContentToEntityBase object.
-   *
-   * @param \Drupal\views\Plugin\ViewsHandlerManager $join_manager
-   *   The views plugin join manager.
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content enabler plugin manager.
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, ViewsHandlerManager $join_manager, GroupContentEnablerManagerInterface $plugin_manager) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-    $this->joinManager = $join_manager;
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('plugin.manager.views.join'),
-      $container->get('plugin.manager.group_content_enabler')
-    );
-  }
-
-  /**
-   * Retrieves the entity type ID this plugin targets.
-   *
-   * Do not return 'group_content', but the actual entity type ID you're trying
-   * to link up to the group_content entity type.
-   *
-   * @return string
-   *   The target entity type ID.
-   */
-  protected abstract function getTargetEntityType();
-
-  /**
-   * Retrieves type of join field to use.
-   *
-   * Can be either 'field' or 'left_field'.
-   *
-   * @return string
-   *   The type of join field to use.
-   */
-  protected abstract function getJoinFieldType();
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function defineOptions() {
-    $options = parent::defineOptions();
-    $options['group_content_plugins']['default'] = [];
-    return $options;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
-    parent::buildOptionsForm($form, $form_state);
-
-    // Retrieve all of the plugins that can serve this entity type.
-    $options = [];
-    foreach ($this->pluginManager->getAll() as $plugin_id => $plugin) {
-      /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-      if ($plugin->getEntityTypeId() === $this->getTargetEntityType()) {
-        $options[$plugin_id] = $plugin->getLabel();
-      }
-    }
-
-    $form['group_content_plugins'] = [
-      '#type' => 'checkboxes',
-      '#title' => $this->t('Filter by plugin'),
-      '#description' => $this->t('Refine the result by plugin. Leave empty to select all plugins, including those that could be added after this relationship was configured.'),
-      '#options' => $options,
-      '#weight' => -2,
-      '#default_value' => $this->options['group_content_plugins'],
-    ];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function query() {
-    $this->ensureMyTable();
-
-    // Build the join definition.
-    $def = $this->definition;
-    $def['table'] = $this->definition['base'];
-    $def['field'] = $this->definition['base field'];
-    $def['left_table'] = $this->tableAlias;
-    $def['left_field'] = $this->realField;
-    $def['adjusted'] = TRUE;
-
-    // Change the join to INNER if the relationship is required.
-    if (!empty($this->options['required'])) {
-      $def['type'] = 'INNER';
-    }
-
-    // If there were extra join conditions added in the definition, use them.
-    if (!empty($this->definition['extra'])) {
-      $def['extra'] = $this->definition['extra'];
-    }
-
-    // We can't run an IN-query on an empty array. So if there are no group
-    // content types yet, we need to make sure the JOIN does not return any GCT
-    // that does not serve the entity type that was configured for this handler
-    // instance.
-    $group_content_type_ids = $this->getGroupContentTypeIds();
-    if (empty($group_content_type_ids)) {
-      $group_content_type_ids = ['***'];
-    }
-
-    // Then add our own join condition, namely the group content type IDs.
-    $def['extra'][] = [
-      $this->getJoinFieldType() => 'type',
-      'value' => $group_content_type_ids,
-    ];
-
-    // Use the standard join plugin unless instructed otherwise.
-    $join_id = !empty($def['join_id']) ? $def['join_id'] : 'standard';
-    $join = $this->joinManager->createInstance($join_id, $def);
-
-    // Add the join using a more verbose alias.
-    $alias = $def['table'] . '_' . $this->table;
-    $this->alias = $this->query->addRelationship($alias, $join, $this->definition['base'], $this->relationship);
-
-    // Add access tags if the base table provides it.
-    $table_data = $this->viewsData->get($def['table']);
-    if (empty($this->query->options['disable_sql_rewrite']) && isset($table_data['table']['base']['access query tag'])) {
-      $access_tag = $table_data['table']['base']['access query tag'];
-      $this->query->addTag($access_tag);
-    }
-  }
-
-  /**
-   * Returns the group content types this relationship should filter on.
-   *
-   * This checks if any plugins were selected on the option form and, in that
-   * case, loads only those group content types available to the selected
-   * plugins. Otherwise, all possible group content types for the relationship's
-   * entity type are loaded.
-   *
-   * This needs to happen live to cover the use case where a group content
-   * plugin is installed on a group type after this relationship has been
-   * configured on a view without any plugins selected.
-   *
-   * @todo Could be cached even more, I guess.
-   *
-   * @return string[]
-   *   The group content type IDs to filter on.
-   */
-  protected function getGroupContentTypeIds() {
-    $plugin_ids = array_filter($this->options['group_content_plugins']);
-
-    $group_content_type_ids = [];
-    foreach ($plugin_ids as $plugin_id) {
-      $group_content_type_ids = array_merge($group_content_type_ids, $this->pluginManager->getGroupContentTypeIds($plugin_id));
-    }
-
-    return $plugin_ids ? $group_content_type_ids : array_keys(GroupContentType::loadByEntityTypeId($this->getTargetEntityType()));
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/views/relationship/GroupContentToEntityReverse.php b/web/modules/group/src/Plugin/views/relationship/GroupContentToEntityReverse.php
deleted file mode 100644
index dfad5b93f2..0000000000
--- a/web/modules/group/src/Plugin/views/relationship/GroupContentToEntityReverse.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\views\relationship;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\group\Entity\GroupContentType;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Drupal\views\Plugin\views\relationship\RelationshipPluginBase;
-use Drupal\views\Plugin\ViewsHandlerManager;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * A relationship handler which reverses group content entity references.
- *
- * @ingroup views_relationship_handlers
- *
- * @ViewsRelationship("group_content_to_entity_reverse")
- */
-class GroupContentToEntityReverse extends GroupContentToEntityBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getTargetEntityType() {
-    return $this->definition['entity_type'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getJoinFieldType() {
-    return 'field';
-  }
-
-}
diff --git a/web/modules/group/src/Plugin/views/relationship/GroupToGroupContent.php b/web/modules/group/src/Plugin/views/relationship/GroupToGroupContent.php
deleted file mode 100644
index 31b566a95a..0000000000
--- a/web/modules/group/src/Plugin/views/relationship/GroupToGroupContent.php
+++ /dev/null
@@ -1,193 +0,0 @@
-<?php
-
-namespace Drupal\group\Plugin\views\relationship;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\group\Entity\GroupContentType;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-use Drupal\views\Plugin\views\relationship\RelationshipPluginBase;
-use Drupal\views\Plugin\ViewsHandlerManager;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * A relationship handler for group content.
- *
- * @ingroup views_relationship_handlers
- *
- * @ViewsRelationship("group_to_group_content")
- */
-class GroupToGroupContent extends RelationshipPluginBase {
-
-  /**
-   * The Views join plugin manager.
-   *
-   * @var \Drupal\views\Plugin\ViewsHandlerManager
-   */
-  protected $joinManager;
-
-  /**
-   * The group content enabler plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * The group content type IDs to filter the join on.
-   *
-   * @var string[]
-   */
-  protected $groupContentTypeIds;
-
-  /**
-   * Constructs a GroupToGroupContent object.
-   *
-   * @param \Drupal\views\Plugin\ViewsHandlerManager $join_manager
-   *   The views plugin join manager.
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content enabler plugin manager.
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, ViewsHandlerManager $join_manager, GroupContentEnablerManagerInterface $plugin_manager) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-    $this->joinManager = $join_manager;
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('plugin.manager.views.join'),
-      $container->get('plugin.manager.group_content_enabler')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function defineOptions() {
-    $options = parent::defineOptions();
-    $options['group_content_plugins']['default'] = [];
-    return $options;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
-    parent::buildOptionsForm($form, $form_state);
-
-    $form['group_content_plugins'] = [
-      '#type' => 'checkboxes',
-      '#title' => $this->t('Filter by plugin'),
-      '#description' => $this->t('Refine the result by plugin. Leave empty to select all plugins, including those that could be added after this relationship was configured.'),
-      '#options' => $this->getContentPluginOptions(),
-      '#weight' => -2,
-      '#default_value' => $this->options['group_content_plugins'],
-    ];
-  }
-
-  /**
-   * Builds the options for the content plugin selection.
-   *
-   * @return string[]
-   *   An array of content plugin labels, keyed by plugin ID.
-   */
-  protected function getContentPluginOptions() {
-    $options = [];
-    foreach ($this->pluginManager->getAll() as $plugin_id => $plugin) {
-      /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-      $options[$plugin_id] = $plugin->getLabel();
-    }
-    return $options;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function query() {
-    $this->ensureMyTable();
-
-    // Build the join definition.
-    $def = $this->definition;
-    $def['table'] = $this->definition['base'];
-    $def['field'] = $this->definition['base field'];
-    $def['left_table'] = $this->tableAlias;
-    $def['left_field'] = $this->realField;
-    $def['adjusted'] = TRUE;
-
-    // Change the join to INNER if the relationship is required.
-    if (!empty($this->options['required'])) {
-      $def['type'] = 'INNER';
-    }
-
-    // If there were extra join conditions added in the definition, use them.
-    if (!empty($this->definition['extra'])) {
-      $def['extra'] = $this->definition['extra'];
-    }
-
-    // We can't run an IN-query on an empty array. So if there are no group
-    // content types yet, we do not add our extra condition to the JOIN.
-    $group_content_type_ids = $this->getGroupContentTypeIds();
-    if (!empty($group_content_type_ids)) {
-      $def['extra'][] = [
-        'field' => 'type',
-        'value' => $group_content_type_ids,
-      ];
-    }
-
-    // Use the standard join plugin unless instructed otherwise.
-    $join_id = !empty($def['join_id']) ? $def['join_id'] : 'standard';
-    $join = $this->joinManager->createInstance($join_id, $def);
-
-    // Add the join using a more verbose alias.
-    $alias = $def['table'] . '_' . $this->table;
-    $this->alias = $this->query->addRelationship($alias, $join, $this->definition['base'], $this->relationship);
-
-    // Add access tags if the base table provides it.
-    $table_data = $this->viewsData->get($def['table']);
-    if (empty($this->query->options['disable_sql_rewrite']) && isset($table_data['table']['base']['access query tag'])) {
-      $access_tag = $table_data['table']['base']['access query tag'];
-      $this->query->addTag($access_tag);
-    }
-  }
-
-  /**
-   * Returns the group content types this relationship should filter on.
-   *
-   * This checks if any plugins were selected on the option form and, in that
-   * case, loads only those group content types available to the selected
-   * plugins. Otherwise, all possible group content types for the relationship's
-   * entity type are loaded.
-   *
-   * This needs to happen live to cover the use case where a group content
-   * plugin is installed on a group type after this relationship has been
-   * configured on a view without any plugins selected.
-   *
-   * @return string[]
-   *   The group content type IDs to filter on.
-   */
-  protected function getGroupContentTypeIds() {
-    // Even though the retrieval needs to happen live, there's nothing stopping
-    // us from statically caching it during runtime.
-    if (!isset($this->groupContentTypeIds)) {
-      $plugin_ids = array_filter($this->options['group_content_plugins']);
-
-      $group_content_type_ids = [];
-      foreach ($plugin_ids as $plugin_id) {
-        $group_content_type_ids = array_merge($group_content_type_ids, $this->pluginManager->getGroupContentTypeIds($plugin_id));
-      }
-
-      $this->groupContentTypeIds = $plugin_ids
-        ? $group_content_type_ids
-        : array_keys(GroupContentType::loadMultiple());
-    }
-
-    return $this->groupContentTypeIds;
-  }
-
-}
diff --git a/web/modules/group/src/ProxyClass/UninstallValidator/GroupContentUninstallValidator.php b/web/modules/group/src/ProxyClass/UninstallValidator/GroupContentUninstallValidator.php
deleted file mode 100644
index fa6cc16637..0000000000
--- a/web/modules/group/src/ProxyClass/UninstallValidator/GroupContentUninstallValidator.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-
-/**
- * This file was generated via php core/scripts/generate-proxy-class.php 'Drupal\group\UninstallValidator\GroupContentUninstallValidator' "modules/group/src".
- */
-
-namespace Drupal\group\ProxyClass\UninstallValidator {
-
-    /**
-     * Provides a proxy class for \Drupal\group\UninstallValidator\GroupContentUninstallValidator.
-     *
-     * @see \Drupal\Component\ProxyBuilder
-     */
-    class GroupContentUninstallValidator implements \Drupal\Core\Extension\ModuleUninstallValidatorInterface
-    {
-
-        use \Drupal\Core\DependencyInjection\DependencySerializationTrait;
-
-        /**
-         * The id of the original proxied service.
-         *
-         * @var string
-         */
-        protected $drupalProxyOriginalServiceId;
-
-        /**
-         * The real proxied service, after it was lazy loaded.
-         *
-         * @var \Drupal\group\UninstallValidator\GroupContentUninstallValidator
-         */
-        protected $service;
-
-        /**
-         * The service container.
-         *
-         * @var \Symfony\Component\DependencyInjection\ContainerInterface
-         */
-        protected $container;
-
-        /**
-         * Constructs a ProxyClass Drupal proxy object.
-         *
-         * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
-         *   The container.
-         * @param string $drupal_proxy_original_service_id
-         *   The service ID of the original service.
-         */
-        public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id)
-        {
-            $this->container = $container;
-            $this->drupalProxyOriginalServiceId = $drupal_proxy_original_service_id;
-        }
-
-        /**
-         * Lazy loads the real service from the container.
-         *
-         * @return object
-         *   Returns the constructed real service.
-         */
-        protected function lazyLoadItself()
-        {
-            if (!isset($this->service)) {
-                $this->service = $this->container->get($this->drupalProxyOriginalServiceId);
-            }
-
-            return $this->service;
-        }
-
-        /**
-         * {@inheritdoc}
-         */
-        public function validate($module)
-        {
-            return $this->lazyLoadItself()->validate($module);
-        }
-
-        /**
-         * {@inheritdoc}
-         */
-        public function setStringTranslation(\Drupal\Core\StringTranslation\TranslationInterface $translation)
-        {
-            return $this->lazyLoadItself()->setStringTranslation($translation);
-        }
-
-    }
-
-}
diff --git a/web/modules/group/src/Routing/GroupAdminRouteSubscriber.php b/web/modules/group/src/Routing/GroupAdminRouteSubscriber.php
deleted file mode 100644
index 44905c4363..0000000000
--- a/web/modules/group/src/Routing/GroupAdminRouteSubscriber.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-namespace Drupal\group\Routing;
-
-use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Routing\RouteSubscriberBase;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * Sets the _admin_route for specific group-related routes.
- */
-class GroupAdminRouteSubscriber extends RouteSubscriberBase {
-
-  /**
-   * The config factory.
-   *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
-   */
-  protected $configFactory;
-
-  /**
-   * Constructs a new GroupAdminRouteSubscriber.
-   *
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *   The config factory.
-   */
-  public function __construct(ConfigFactoryInterface $config_factory) {
-    $this->configFactory = $config_factory;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function alterRoutes(RouteCollection $collection) {
-    if ($this->configFactory->get('group.settings')->get('use_admin_theme')) {
-      foreach ($collection->all() as $route) {
-        if ($route->hasOption('_group_operation_route')) {
-          $route->setOption('_admin_route', TRUE);
-        }
-      }
-    }
-  }
-
-}
diff --git a/web/modules/group/src/UninstallValidator/GroupContentUninstallValidator.php b/web/modules/group/src/UninstallValidator/GroupContentUninstallValidator.php
deleted file mode 100644
index b09053c5c9..0000000000
--- a/web/modules/group/src/UninstallValidator/GroupContentUninstallValidator.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-namespace Drupal\group\UninstallValidator;
-
-use Drupal\Core\Entity\Query\QueryFactory;
-use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\Core\StringTranslation\TranslationInterface;
-use Drupal\group\Entity\GroupContentType;
-use Drupal\group\Plugin\GroupContentEnablerManagerInterface;
-
-class GroupContentUninstallValidator implements ModuleUninstallValidatorInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The query factory to create entity queries.
-   *
-   * @var \Drupal\Core\Entity\Query\QueryFactory
-   */
-  protected $queryFactory;
-
-  /**
-   * The group content plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * Constructs a new GroupContentUninstallValidator object.
-   *
-   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
-   *   The string translation service.
-   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
-   *   The entity query object.
-   * @param \Drupal\group\Plugin\GroupContentEnablerManagerInterface $plugin_manager
-   *   The group content plugin manager.
-   */
-  public function __construct(TranslationInterface $string_translation, QueryFactory $query_factory, GroupContentEnablerManagerInterface $plugin_manager) {
-    $this->stringTranslation = $string_translation;
-    $this->queryFactory = $query_factory;
-    $this->pluginManager = $plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validate($module) {
-    $reasons = $plugin_names = [];
-
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    foreach ($this->pluginManager->getAll() as $plugin_id => $plugin) {
-      if ($plugin->getProvider() == $module && $this->hasGroupContent($plugin_id)) {
-        $plugin_names[] = $plugin->getLabel();
-      }
-    }
-
-    if (!empty($plugin_names)) {
-      $reasons[] = $this->t('The following group content plugins still have content for them: %plugins.', ['%plugins' => implode(', ', $plugin_names)]);
-    }
-
-    return $reasons;
-  }
-
-  /**
-   * Determines if there is any group content for a content enabler plugin.
-   *
-   * @param string $plugin_id
-   *   The group content enabler plugin ID to check for group content.
-   *
-   * @return bool
-   *   Whether there are group content entities for the given plugin ID.
-   */
-  protected function hasGroupContent($plugin_id) {
-    $group_content_types = array_keys(GroupContentType::loadByContentPluginId($plugin_id));
-
-    if (empty($group_content_types)) {
-      return FALSE;
-    }
-
-    $entity_count = $this->queryFactory->get('group_content')
-      ->condition('type', $group_content_types, 'IN')
-      ->count()
-      ->execute();
-
-    return (bool) $entity_count;
-  }
-
-}
diff --git a/web/modules/group/templates/group-content.html.twig b/web/modules/group/templates/group-content.html.twig
deleted file mode 100644
index fe7e44f25e..0000000000
--- a/web/modules/group/templates/group-content.html.twig
+++ /dev/null
@@ -1,54 +0,0 @@
-{#
-/**
- * @file
- * Default theme implementation to display a group content entity.
- *
- * Available variables:
- * - group_content: The group content entity with limited access to object
- *   properties and methods. Only "getter" methods (method names starting with
- *   "get", "has", or "is") and a few common methods such as "id" and "label"
- *   are available. Calling other methods (such as group.delete) will result in
- *   an exception.
- * - label: The title of the group content entity.
- * - content: All group content items. Use {{ content }} to print them all,
- *   or print a subset such as {{ content.field_example }}. Use
- *   {{ content|without('field_example') }} to temporarily suppress the
- *   printing of a given child element.
- * - url: Direct URL of the current group content entity.
- * - attributes: HTML attributes for the containing element.
- *   The attributes.class element may contain one or more of the following
- *   classes:
- *   - group-content: The current template type (also known as a "theming hook").
- *   - group-content--[type]: The current group content type.
- *   - group-content--[view_mode]: The View Mode of the group content.
- * - title_attributes: Same as attributes, except applied to the main title
- *   tag that appears in the template.
- * - content_attributes: Same as attributes, except applied to the main
- *   content tag that appears in the template.
- * - title_prefix: Additional output populated by modules, intended to be
- *   displayed in front of the main title tag that appears in the template.
- * - title_suffix: Additional output populated by modules, intended to be
- *   displayed after the main title tag that appears in the template.
- * - view_mode: View mode; for example, "teaser" or "full".
- * - page: Flag for the full page state. Will be true if view_mode is 'full'.
- *
- * @see template_preprocess_group()
- *
- * @ingroup themeable
- */
-#}
-<div{{ attributes }}>
-
-    {{ title_prefix }}
-    {% if not page %}
-        <h2{{ title_attributes }}>
-            <a href="{{ url }}" rel="bookmark">{{ label }}</a>
-        </h2>
-    {% endif %}
-    {{ title_suffix }}
-
-    <div{{ content_attributes }}>
-        {{ content }}
-    </div>
-
-</div>
diff --git a/web/modules/group/templates/group.html.twig b/web/modules/group/templates/group.html.twig
deleted file mode 100644
index b73ba3bff2..0000000000
--- a/web/modules/group/templates/group.html.twig
+++ /dev/null
@@ -1,56 +0,0 @@
-{#
-/**
- * @file
- * Default theme implementation to display a group.
- *
- * Available variables:
- * - group: The group entity with limited access to object properties and
- *   methods. Only "getter" methods (method names starting with "get", "has",
- *   or "is") and a few common methods such as "id" and "label" are available.
- *   Calling other methods (such as group.delete) will result in an exception.
- * - label: The title of the group.
- * - content: All group items. Use {{ content }} to print them all,
- *   or print a subset such as {{ content.field_example }}. Use
- *   {{ content|without('field_example') }} to temporarily suppress the
- *   printing of a given child element.
- * - url: Direct URL of the current group.
- * - attributes: HTML attributes for the containing element.
- *   The attributes.class element may contain one or more of the following
- *   classes:
- *   - group: The current template type (also known as a "theming hook").
- *   - group--[type]: The current group type. For example, if the group is a
- *     "Classroom" it would result in "group--classroom". Note that the machine
- *     name will often be in a short form of the human readable label.
- *   - group--[view_mode]: The View Mode of the group; for example, a
- *     teaser would result in: "group--teaser", and full: "group--full".
- * - title_attributes: Same as attributes, except applied to the main title
- *   tag that appears in the template.
- * - content_attributes: Same as attributes, except applied to the main
- *   content tag that appears in the template.
- * - title_prefix: Additional output populated by modules, intended to be
- *   displayed in front of the main title tag that appears in the template.
- * - title_suffix: Additional output populated by modules, intended to be
- *   displayed after the main title tag that appears in the template.
- * - view_mode: View mode; for example, "teaser" or "full".
- * - page: Flag for the full page state. Will be true if view_mode is 'full'.
- *
- * @see template_preprocess_group()
- *
- * @ingroup themeable
- */
-#}
-<div{{ attributes }}>
-
-    {{ title_prefix }}
-    {% if not page %}
-        <h2{{ title_attributes }}>
-            <a href="{{ url }}" rel="bookmark">{{ label }}</a>
-        </h2>
-    {% endif %}
-    {{ title_suffix }}
-
-    <div{{ content_attributes }}>
-        {{ content }}
-    </div>
-
-</div>
diff --git a/web/modules/group/tests/modules/group_test_config/config/install/group.content_type.default-group_membership.yml b/web/modules/group/tests/modules/group_test_config/config/install/group.content_type.default-group_membership.yml
deleted file mode 100644
index b39a0225b9..0000000000
--- a/web/modules/group/tests/modules/group_test_config/config/install/group.content_type.default-group_membership.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  config:
-    - group.type.default
-  module:
-    - user
-id: default-group_membership
-label: 'Default label: Group membership'
-description: 'Adds users to groups as members.'
-group_type: default
-content_plugin: group_membership
-plugin_config:
-  group_cardinality: 99
-  entity_cardinality: 1
diff --git a/web/modules/group/tests/modules/group_test_config/config/install/group.role.default-custom.yml b/web/modules/group/tests/modules/group_test_config/config/install/group.role.default-custom.yml
deleted file mode 100644
index c1703b9205..0000000000
--- a/web/modules/group/tests/modules/group_test_config/config/install/group.role.default-custom.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  config:
-    - group.type.default
-id: default-custom
-label: Custom
-weight: 0
-internal: false
-audience: member
-group_type: default
-permissions_ui: true
-permissions:
-  - 'join group'
-  - 'view group'
diff --git a/web/modules/group/tests/modules/group_test_config/config/install/group.role.default-member.yml b/web/modules/group/tests/modules/group_test_config/config/install/group.role.default-member.yml
deleted file mode 100644
index b6cb1f9793..0000000000
--- a/web/modules/group/tests/modules/group_test_config/config/install/group.role.default-member.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  config:
-    - group.type.default
-id: default-member
-label: Member
-weight: -100
-internal: true
-audience: member
-group_type: default
-permissions_ui: true
-permissions:
-  - 'view group'
-  - 'leave group'
diff --git a/web/modules/group/tests/modules/group_test_config/config/install/group.role.default-outsider.yml b/web/modules/group/tests/modules/group_test_config/config/install/group.role.default-outsider.yml
deleted file mode 100644
index 316c51265d..0000000000
--- a/web/modules/group/tests/modules/group_test_config/config/install/group.role.default-outsider.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  config:
-    - group.type.default
-id: default-outsider
-label: Outsider
-weight: -101
-internal: true
-audience: outsider
-group_type: default
-permissions_ui: true
-permissions:
-  - 'join group'
-  - 'view group'
diff --git a/web/modules/group/tests/modules/group_test_config/config/install/group.type.default.yml b/web/modules/group/tests/modules/group_test_config/config/install/group.type.default.yml
deleted file mode 100644
index 64376fe6dd..0000000000
--- a/web/modules/group/tests/modules/group_test_config/config/install/group.type.default.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-langcode: en
-status: true
-dependencies: {  }
-id: default
-label: 'Default label'
-description: 'Default description.'
diff --git a/web/modules/group/tests/modules/group_test_config/group_test_config.info.yml b/web/modules/group/tests/modules/group_test_config/group_test_config.info.yml
deleted file mode 100644
index 30b28acc3b..0000000000
--- a/web/modules/group/tests/modules/group_test_config/group_test_config.info.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-name: 'Group configuration tests'
-description: 'Support module for group configuration tests.'
-package: 'Testing'
-type: 'module'
-# version: '1.0'
-# core: '8.x'
-
-# Information added by Drupal.org packaging script on 2017-02-20
-version: '8.x-1.0-beta5'
-core: '8.x'
-project: 'group'
-datestamp: 1487606183
diff --git a/web/modules/group/tests/modules/group_test_config/sync/group.type.import.yml b/web/modules/group/tests/modules/group_test_config/sync/group.type.import.yml
deleted file mode 100644
index 10cafbbf5b..0000000000
--- a/web/modules/group/tests/modules/group_test_config/sync/group.type.import.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-langcode: en
-status: true
-dependencies: {  }
-id: import
-label: 'Import label'
-description: 'Import description.'
diff --git a/web/modules/group/tests/modules/group_test_plugin/group_test_plugin.info.yml b/web/modules/group/tests/modules/group_test_plugin/group_test_plugin.info.yml
deleted file mode 100644
index 07dfc24f14..0000000000
--- a/web/modules/group/tests/modules/group_test_plugin/group_test_plugin.info.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: 'Group test plugin'
-description: 'Provides group plugins to run tests with.'
-package: 'Testing'
-type: 'module'
-# version: '1.0'
-# core: '8.x'
-dependencies:
-  - group
-  - language
-
-# Information added by Drupal.org packaging script on 2017-02-20
-version: '8.x-1.0-beta5'
-core: '8.x'
-project: 'group'
-datestamp: 1487606183
diff --git a/web/modules/group/tests/modules/group_test_plugin/src/Plugin/GroupContentEnabler/UserAsContent.php b/web/modules/group/tests/modules/group_test_plugin/src/Plugin/GroupContentEnabler/UserAsContent.php
deleted file mode 100644
index 0f20e21f8f..0000000000
--- a/web/modules/group/tests/modules/group_test_plugin/src/Plugin/GroupContentEnabler/UserAsContent.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-namespace Drupal\group_test_plugin\Plugin\GroupContentEnabler;
-
-use Drupal\group\Plugin\GroupContentEnablerBase;
-
-/**
- * Provides a content enabler for users.
- *
- * @GroupContentEnabler(
- *   id = "user_as_content",
- *   label = @Translation("Group user"),
- *   description = @Translation("Adds users to groups without making them members."),
- *   entity_type_id = "user",
- *   pretty_path_key = "user",
- *   reference_label = @Translation("Username"),
- *   reference_description = @Translation("The name of the user you want to add to the group")
- * )
- */
-class UserAsContent extends GroupContentEnablerBase {
-}
diff --git a/web/modules/group/tests/modules/group_test_views/group_test_views.info.yml b/web/modules/group/tests/modules/group_test_views/group_test_views.info.yml
deleted file mode 100644
index 3f45e21299..0000000000
--- a/web/modules/group/tests/modules/group_test_views/group_test_views.info.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: 'Group test views'
-description: 'Provides default views for group views tests.'
-package: 'Testing'
-type: 'module'
-# version: '1.0'
-# core: '8.x'
-dependencies:
-  - group
-  - views
-  - language
-
-# Information added by Drupal.org packaging script on 2017-02-20
-version: '8.x-1.0-beta5'
-core: '8.x'
-project: 'group'
-datestamp: 1487606183
diff --git a/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_content_to_entity_relationship.yml b/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_content_to_entity_relationship.yml
deleted file mode 100644
index 954c68baf7..0000000000
--- a/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_content_to_entity_relationship.yml
+++ /dev/null
@@ -1,222 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  module:
-    - group
-    - user
-id: test_group_content_to_entity_relationship
-label: test_group_content_to_entity_relationship
-module: views
-description: ''
-tag: ''
-base_table: group_content_field_data
-base_field: id
-core: 8.x
-display:
-  default:
-    display_plugin: default
-    id: default
-    display_title: Master
-    position: 0
-    display_options:
-      access:
-        type: none
-        options: {  }
-      cache:
-        type: tag
-        options: {  }
-      query:
-        type: views_query
-        options:
-          disable_sql_rewrite: false
-          distinct: false
-          replica: false
-          query_comment: ''
-          query_tags: {  }
-      exposed_form:
-        type: basic
-        options:
-          submit_button: Apply
-          reset_button: false
-          reset_button_label: Reset
-          exposed_sorts_label: 'Sort by'
-          expose_sort_order: true
-          sort_asc_label: Asc
-          sort_desc_label: Desc
-      pager:
-        type: none
-        options:
-          offset: 0
-      style:
-        type: default
-        options:
-          grouping: {  }
-          row_class: ''
-          default_row_class: true
-          uses_fields: false
-      row:
-        type: fields
-        options:
-          inline: {  }
-          separator: ''
-          hide_empty: false
-          default_field_elements: true
-      fields:
-        id:
-          id: id
-          table: group_content_field_data
-          field: id
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: 'Group content ID'
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: number_integer
-          settings:
-            thousand_separator: ''
-            prefix_suffix: true
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: group_content
-          entity_field: id
-          plugin_id: field
-        uid:
-          id: uid
-          table: users_field_data
-          field: uid
-          relationship: gc__user
-          group_type: group
-          admin_label: ''
-          label: 'User ID'
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: number_integer
-          settings:
-            thousand_separator: ''
-            prefix_suffix: true
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: user
-          entity_field: uid
-          plugin_id: field
-      filters: {  }
-      sorts: {  }
-      header: {  }
-      footer: {  }
-      empty: {  }
-      relationships:
-        gc__user:
-          id: gc__user
-          table: group_content_field_data
-          field: gc__user
-          relationship: none
-          group_type: group
-          admin_label: 'Group content User'
-          required: true
-          group_content_plugins:
-            group_membership: group_membership
-          entity_type: group_content
-          plugin_id: group_content_to_entity
-      arguments: {  }
-      display_extenders: {  }
-    cache_metadata:
-      max-age: -1
-      contexts:
-        - 'languages:language_content'
-        - 'languages:language_interface'
-      tags: {  }
diff --git a/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_content_to_entity_reverse_relationship.yml b/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_content_to_entity_reverse_relationship.yml
deleted file mode 100644
index 52ea00f4be..0000000000
--- a/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_content_to_entity_reverse_relationship.yml
+++ /dev/null
@@ -1,239 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  module:
-    - group
-    - user
-id: test_group_content_to_entity_reverse_relationship
-label: test_group_content_to_entity_reverse_relationship
-module: views
-description: ''
-tag: ''
-base_table: users_field_data
-base_field: uid
-core: 8.x
-display:
-  default:
-    display_plugin: default
-    id: default
-    display_title: Master
-    position: 0
-    display_options:
-      access:
-        type: perm
-        options:
-          perm: 'access user profiles'
-      cache:
-        type: tag
-        options: {  }
-      query:
-        type: views_query
-        options:
-          disable_sql_rewrite: false
-          distinct: false
-          replica: false
-          query_comment: ''
-          query_tags: {  }
-      exposed_form:
-        type: basic
-        options:
-          submit_button: Apply
-          reset_button: false
-          reset_button_label: Reset
-          exposed_sorts_label: 'Sort by'
-          expose_sort_order: true
-          sort_asc_label: Asc
-          sort_desc_label: Desc
-      pager:
-        type: mini
-        options:
-          items_per_page: 10
-          offset: 0
-          id: 0
-          total_pages: null
-          expose:
-            items_per_page: false
-            items_per_page_label: 'Items per page'
-            items_per_page_options: '5, 10, 25, 50'
-            items_per_page_options_all: false
-            items_per_page_options_all_label: '- All -'
-            offset: false
-            offset_label: Offset
-          tags:
-            previous: ‹‹
-            next: ››
-      style:
-        type: default
-        options:
-          grouping: {  }
-          row_class: ''
-          default_row_class: true
-          uses_fields: false
-      row:
-        type: fields
-        options:
-          inline: {  }
-          separator: ''
-          hide_empty: false
-          default_field_elements: true
-      fields:
-        id:
-          id: id
-          table: group_content_field_data
-          field: id
-          relationship: group_content
-          group_type: group
-          admin_label: ''
-          label: 'Group content ID'
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: number_integer
-          settings:
-            thousand_separator: ''
-            prefix_suffix: true
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: group_content
-          entity_field: id
-          plugin_id: field
-        uid:
-          id: uid
-          table: users_field_data
-          field: uid
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: 'User ID'
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: number_integer
-          settings:
-            thousand_separator: ''
-            prefix_suffix: true
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: user
-          entity_field: uid
-          plugin_id: field
-      filters: {  }
-      sorts: {  }
-      header: {  }
-      footer: {  }
-      empty: {  }
-      relationships:
-        group_content:
-          id: group_content
-          table: users_field_data
-          field: group_content
-          relationship: none
-          group_type: group
-          admin_label: 'User group content'
-          required: true
-          group_content_plugins:
-            group_membership: group_membership
-          entity_type: user
-          plugin_id: group_content_to_entity_reverse
-      arguments: {  }
-      display_extenders: {  }
-    cache_metadata:
-      max-age: -1
-      contexts:
-        - 'languages:language_content'
-        - 'languages:language_interface'
-        - url.query_args
-        - user.permissions
-      tags: {  }
diff --git a/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_id_argument.yml b/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_id_argument.yml
deleted file mode 100644
index b8026f8e23..0000000000
--- a/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_id_argument.yml
+++ /dev/null
@@ -1,202 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  module:
-    - group
-id: test_group_id_argument
-label: test_group_id_argument
-module: views
-description: ''
-tag: ''
-base_table: groups_field_data
-base_field: id
-core: 8.x
-display:
-  default:
-    display_plugin: default
-    id: default
-    display_title: Master
-    position: 0
-    display_options:
-      access:
-        type: none
-      cache:
-        type: tag
-        options: {  }
-      query:
-        type: views_query
-        options:
-          disable_sql_rewrite: false
-          distinct: false
-          replica: false
-          query_comment: ''
-          query_tags: {  }
-      exposed_form:
-        type: basic
-        options:
-          submit_button: Apply
-          reset_button: false
-          reset_button_label: Reset
-          exposed_sorts_label: 'Sort by'
-          expose_sort_order: true
-          sort_asc_label: Asc
-          sort_desc_label: Desc
-      pager:
-        type: none
-        options:
-          offset: 0
-      style:
-        type: default
-        options:
-          grouping: {  }
-          row_class: ''
-          default_row_class: true
-      row:
-        type: fields
-        options:
-          default_field_elements: true
-          inline: {  }
-          separator: ''
-          hide_empty: false
-      fields:
-        id:
-          id: id
-          table: groups_field_data
-          field: id
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: ''
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: false
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: number_integer
-          settings:
-            thousand_separator: ''
-            prefix_suffix: true
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: group
-          entity_field: id
-          plugin_id: field
-      filters: {  }
-      sorts: {  }
-      title: test_group_id_argument
-      header: {  }
-      footer: {  }
-      empty: {  }
-      relationships: {  }
-      arguments:
-        id:
-          id: id
-          table: groups_field_data
-          field: id
-          relationship: none
-          group_type: group
-          admin_label: ''
-          default_action: ignore
-          exception:
-            value: all
-            title_enable: false
-            title: All
-          title_enable: true
-          title: '{{ arguments.id }}'
-          default_argument_type: fixed
-          default_argument_options:
-            argument: ''
-          default_argument_skip_url: false
-          summary_options:
-            base_path: ''
-            count: true
-            items_per_page: 25
-            override: false
-          summary:
-            sort_order: asc
-            number_of_records: 0
-            format: default_summary
-          specify_validation: false
-          validate:
-            type: none
-            fail: 'not found'
-          validate_options: {  }
-          break_phrase: false
-          not: false
-          entity_type: group
-          entity_field: id
-          plugin_id: group_id
-      display_extenders: {  }
-      use_more: false
-      use_more_always: true
-      use_more_text: more
-      link_url: ''
-      link_display: '0'
-    cache_metadata:
-      contexts:
-        - 'languages:language_content'
-        - 'languages:language_interface'
-        - url
-      cacheable: false
-      max-age: -1
-      tags: {  }
-  page_1:
-    display_plugin: page
-    id: page_1
-    display_title: Page
-    position: 1
-    display_options:
-      display_extenders: {  }
-      path: test-id-argument
-    cache_metadata:
-      contexts:
-        - 'languages:language_content'
-        - 'languages:language_interface'
-        - url
-      cacheable: false
-      max-age: -1
-      tags: {  }
diff --git a/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_to_group_content_relationship.yml b/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_to_group_content_relationship.yml
deleted file mode 100644
index 4d916d1437..0000000000
--- a/web/modules/group/tests/modules/group_test_views/test_views/views.view.test_group_to_group_content_relationship.yml
+++ /dev/null
@@ -1,221 +0,0 @@
-langcode: en
-status: true
-dependencies:
-  module:
-    - group
-id: test_group_to_group_content_relationship
-label: test_group_to_group_content_relationship
-module: views
-description: ''
-tag: ''
-base_table: groups_field_data
-base_field: id
-core: 8.x
-display:
-  default:
-    display_plugin: default
-    id: default
-    display_title: Master
-    position: 0
-    display_options:
-      access:
-        type: none
-        options: {  }
-      cache:
-        type: tag
-        options: {  }
-      query:
-        type: views_query
-        options:
-          disable_sql_rewrite: false
-          distinct: false
-          replica: false
-          query_comment: ''
-          query_tags: {  }
-      exposed_form:
-        type: basic
-        options:
-          submit_button: Apply
-          reset_button: false
-          reset_button_label: Reset
-          exposed_sorts_label: 'Sort by'
-          expose_sort_order: true
-          sort_asc_label: Asc
-          sort_desc_label: Desc
-      pager:
-        type: none
-        options:
-          offset: 0
-      style:
-        type: default
-        options:
-          grouping: {  }
-          row_class: ''
-          default_row_class: true
-          uses_fields: false
-      row:
-        type: fields
-        options:
-          inline: {  }
-          separator: ''
-          hide_empty: false
-          default_field_elements: true
-      fields:
-        id:
-          id: id
-          table: groups_field_data
-          field: id
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: 'Group ID'
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: number_integer
-          settings:
-            thousand_separator: ''
-            prefix_suffix: true
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: group
-          entity_field: id
-          plugin_id: field
-        id_1:
-          id: id_1
-          table: group_content_field_data
-          field: id
-          relationship: group_content_id
-          group_type: group
-          admin_label: ''
-          label: 'Group content ID'
-          exclude: false
-          alter:
-            alter_text: false
-            text: ''
-            make_link: false
-            path: ''
-            absolute: false
-            external: false
-            replace_spaces: false
-            path_case: none
-            trim_whitespace: false
-            alt: ''
-            rel: ''
-            link_class: ''
-            prefix: ''
-            suffix: ''
-            target: ''
-            nl2br: false
-            max_length: 0
-            word_boundary: true
-            ellipsis: true
-            more_link: false
-            more_link_text: ''
-            more_link_path: ''
-            strip_tags: false
-            trim: false
-            preserve_tags: ''
-            html: false
-          element_type: ''
-          element_class: ''
-          element_label_type: ''
-          element_label_class: ''
-          element_label_colon: true
-          element_wrapper_type: ''
-          element_wrapper_class: ''
-          element_default_classes: true
-          empty: ''
-          hide_empty: false
-          empty_zero: false
-          hide_alter_empty: true
-          click_sort_column: value
-          type: number_integer
-          settings:
-            thousand_separator: ''
-            prefix_suffix: true
-          group_column: value
-          group_columns: {  }
-          group_rows: true
-          delta_limit: 0
-          delta_offset: 0
-          delta_reversed: false
-          delta_first_last: false
-          multi_type: separator
-          separator: ', '
-          field_api_classes: false
-          entity_type: group_content
-          entity_field: id
-          plugin_id: field
-      filters: {  }
-      sorts: {  }
-      header: {  }
-      footer: {  }
-      empty: {  }
-      relationships:
-        group_content_id:
-          id: group_content_id
-          table: groups_field_data
-          field: group_content_id
-          relationship: none
-          group_type: group
-          admin_label: 'Group content'
-          required: true
-          group_content_plugins:
-            group_membership: group_membership
-          entity_type: group
-          plugin_id: group_to_group_content
-      arguments: {  }
-      display_extenders: {  }
-    cache_metadata:
-      max-age: -1
-      contexts:
-        - 'languages:language_content'
-        - 'languages:language_interface'
-      tags: {  }
diff --git a/web/modules/group/tests/src/Kernel/GroupContentCrudHookTest.php b/web/modules/group/tests/src/Kernel/GroupContentCrudHookTest.php
deleted file mode 100644
index cdb23811ce..0000000000
--- a/web/modules/group/tests/src/Kernel/GroupContentCrudHookTest.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel;
-
-/**
- * Tests the way group content entities react to entity CRUD events.
- *
- * @group group
- */
-class GroupContentCrudHookTest extends GroupKernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    // Required to be able to delete accounts. See User::postDelete().
-    $this->installSchema('user', ['users_data']);
-  }
-
-  /**
-   * Tests that a grouped entity deletion triggers group content deletion.
-   */
-  public function testGroupedEntityDeletion() {
-    $account = $this->createUser();
-    $group = $this->createGroup(['uid' => $account->id()]);
-
-    $count = count($group->getContent());
-    $account->delete();
-    $this->assertCount($count - 1, $group->getContent(), "Deleting the group owner's account reduces the group content count by one.");
-  }
-
-  /**
-   * Tests that an ungrouped entity deletion triggers no group content deletion.
-   */
-  public function testUngroupedEntityDeletion() {
-    $group = $this->createGroup();
-
-    $count = count($group->getContent());
-    $this->createUser()->delete();
-    $this->assertCount($count, $group->getContent(), "Deleting an ungrouped user account does not remove any group content.");
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/GroupCreatorTest.php b/web/modules/group/tests/src/Kernel/GroupCreatorTest.php
deleted file mode 100644
index 8b55cc194a..0000000000
--- a/web/modules/group/tests/src/Kernel/GroupCreatorTest.php
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel;
-
-/**
- * Tests the behavior of group creators.
- *
- * @group group
- */
-class GroupCreatorTest extends GroupKernelTestBase {
-
-  /**
-   * The account to use as the group creator.
-   *
-   * @var \Drupal\Core\Session\AccountInterface
-   */
-  protected $account;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->account = $this->createUser();
-  }
-
-  /**
-   * Tests that a group creator is automatically a member.
-   */
-  public function testCreatorMembership() {
-    $group = $this->createGroup(['uid' => $this->account->id()]);
-
-    $group_membership = $group->getMember($this->account);
-    $this->assertNotFalse($group_membership, 'Membership could be loaded for the group creator.');
-
-    /** @var \Drupal\group\Entity\Storage\GroupRoleStorageInterface $group_role_storage */
-    $group_role_storage = $this->entityTypeManager->getStorage('group_role');
-    $group_roles = $group_role_storage->loadByUserAndGroup($this->account, $group);
-
-    $this->assertCount(1, $group_roles, 'Membership has just one role.');
-    $this->assertEquals('default-member', key($group_roles), 'Membership has the member role.');
-  }
-
-  /**
-   * Tests that a group creator gets the configured roles.
-   */
-  public function testCreatorRoles() {
-    /* @var \Drupal\group\Entity\GroupTypeInterface $group_type */
-    $group_type = $this->entityTypeManager->getStorage('group_type')->load('default');
-    $group_type->set('creator_roles', ['default-custom']);
-    $group_type->save();
-
-    $group = $this->createGroup(['uid' => $this->account->id()]);
-
-    /** @var \Drupal\group\Entity\Storage\GroupRoleStorageInterface $group_role_storage */
-    $group_role_storage = $this->entityTypeManager->getStorage('group_role');
-    $group_roles = $group_role_storage->loadByUserAndGroup($this->account, $group);
-    ksort($group_roles);
-
-    $this->assertCount(2, $group_roles, 'Membership has two roles.');
-
-    $group_role = reset($group_roles);
-    $this->assertEquals('default-custom', $group_role->id(), 'Membership has the custom role.');
-
-    $group_role = next($group_roles);
-    $this->assertEquals('default-member', $group_role->id(), 'Membership has the member role.');
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/GroupKernelTestBase.php b/web/modules/group/tests/src/Kernel/GroupKernelTestBase.php
deleted file mode 100644
index d791c59ead..0000000000
--- a/web/modules/group/tests/src/Kernel/GroupKernelTestBase.php
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel;
-
-use Drupal\Core\Session\AccountInterface;
-use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
-
-/**
- * Defines an abstract test base for group kernel tests.
- */
-abstract class GroupKernelTestBase extends EntityKernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = ['group', 'group_test_config'];
-
-  /**
-   * The entity type manager service.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The content enabler plugin manager.
-   *
-   * @var \Drupal\group\Plugin\GroupContentEnablerManagerInterface
-   */
-  protected $pluginManager;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->entityTypeManager = $this->container->get('entity_type.manager');
-    $this->pluginManager = $this->container->get('plugin.manager.group_content_enabler');
-
-    $this->installConfig(['group', 'group_test_config']);
-    $this->installEntitySchema('group');
-    $this->installEntitySchema('group_type');
-    $this->installEntitySchema('group_content');
-    $this->installEntitySchema('group_content_type');
-
-    $this->setCurrentUser($this->createUser());
-  }
-
-  /**
-   * Set the current user so group creation can rely on it.
-   *
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account to set as the current user.
-   */
-  protected function setCurrentUser(AccountInterface $account) {
-    $this->container->get('current_user')->setAccount($account);
-  }
-
-  /**
-   * Creates a group.
-   *
-   * @param array $values
-   *   (optional) The values used to create the entity.
-   *
-   * @return \Drupal\group\Entity\Group
-   *   The created group entity.
-   */
-  protected function createGroup($values = []) {
-    $group = $this->entityTypeManager->getStorage('group')->create($values + [
-      'type' => 'default',
-      'label' => $this->randomMachineName(),
-    ]);
-    $group->enforceIsNew();
-    $group->save();
-    return $group;
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/GroupTest.php b/web/modules/group/tests/src/Kernel/GroupTest.php
deleted file mode 100644
index 92a0dad5ea..0000000000
--- a/web/modules/group/tests/src/Kernel/GroupTest.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel;
-
-/**
- * Tests the general behavior of group entities.
- *
- * @coversDefaultClass \Drupal\group\Entity\Group
- * @group group
- */
-class GroupTest extends GroupKernelTestBase {
-
-  /**
-   * The group we will use to test methods on.
-   *
-   * @var \Drupal\group\Entity\Group
-   */
-  protected $group;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->group = $this->createGroup();
-  }
-
-  /**
-   * Tests the addition of a member to a group.
-   *
-   * @covers ::addMember
-   */
-  public function testAddMember() {
-    $account = $this->createUser();
-    $this->assertFalse($this->group->getMember($account), 'The user is not automatically member of the group.');
-    $this->group->addMember($account);
-    $this->assertNotFalse($this->group->getMember($account), 'Successfully added a member.');
-  }
-
-  /**
-   * Tests the removal of a member from a group.
-   *
-   * @covers ::removeMember
-   * @depends testAddMember
-   */
-  public function testRemoveMember() {
-    $account = $this->createUser();
-    $this->group->addMember($account);
-    $this->group->removeMember($account);
-    $this->assertFalse($this->group->getMember($account), 'Successfully removed a member.');
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/GroupTokenReplaceTest.php b/web/modules/group/tests/src/Kernel/GroupTokenReplaceTest.php
deleted file mode 100644
index f5d94885aa..0000000000
--- a/web/modules/group/tests/src/Kernel/GroupTokenReplaceTest.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel;
-
-use Drupal\Component\Render\FormattableMarkup;
-use Drupal\Core\Render\BubbleableMetadata;
-use Drupal\group\Entity\Group;
-use Drupal\Tests\system\Kernel\Token\TokenReplaceKernelTestBase;
-
-/**
- * Generates text using placeholders for dummy content to check group token
- * replacement.
- *
- * @group group
- */
-class GroupTokenReplaceTest extends TokenReplaceKernelTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['group', 'group_test_config'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->installConfig(['group', 'group_test_config']);
-    $this->installEntitySchema('group');
-    $this->installEntitySchema('group_type');
-    $this->installEntitySchema('group_content');
-    $this->installEntitySchema('group_content_type');
-  }
-
-  /**
-   * Tests the tokens replacement for group.
-   */
-  function testGroupTokenReplacement() {
-    $url_options = [
-      'absolute' => TRUE,
-      'language' => $this->interfaceLanguage,
-    ];
-
-    // Create a user and a group.
-    $account = $this->createUser();
-
-    /* @var \Drupal\group\Entity\GroupInterface $group */
-    $group = Group::create([
-      'type' => 'default',
-      'uid' => $account->id(),
-      'label' => $this->randomMachineName(),
-    ]);
-    $group->save();
-
-    // Generate and test tokens.
-    $tests = [];
-    $tests['[group:id]'] = $group->id();
-    $tests['[group:type]'] = 'default';
-    $tests['[group:type-name]'] = 'Default label';
-    $tests['[group:langcode]'] = $group->language()->getId();
-    $tests['[group:url]'] = $group->url('canonical', $url_options);
-    $tests['[group:edit-url]'] = $group->url('edit-form', $url_options);
-    $tests['[group:author]'] = $account->getUsername();
-    $tests['[group:author:uid]'] = $group->getOwnerId();
-    $tests['[group:author:name]'] = $account->getUsername();
-    $tests['[group:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($group->getCreatedTime(), ['langcode' => $this->interfaceLanguage->getId()]);
-    $tests['[group:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($group->getChangedTime(), ['langcode' => $this->interfaceLanguage->getId()]);
-
-    $base_bubbleable_metadata = BubbleableMetadata::createFromObject($group);
-
-    $metadata_tests = [];
-    $metadata_tests['[group:id]'] = $base_bubbleable_metadata;
-    $metadata_tests['[group:type]'] = $base_bubbleable_metadata;
-    $metadata_tests['[group:type-name]'] = $base_bubbleable_metadata;
-    $metadata_tests['[group:langcode]'] = $base_bubbleable_metadata;
-    $metadata_tests['[group:url]'] = $base_bubbleable_metadata;
-    $metadata_tests['[group:edit-url]'] = $base_bubbleable_metadata;
-    $bubbleable_metadata = clone $base_bubbleable_metadata;
-    $metadata_tests['[group:author]'] = $bubbleable_metadata->addCacheTags(['user:1']);
-    $metadata_tests['[group:author:uid]'] = $bubbleable_metadata;
-    $metadata_tests['[group:author:name]'] = $bubbleable_metadata;
-    $bubbleable_metadata = clone $base_bubbleable_metadata;
-    $metadata_tests['[group:created:since]'] = $bubbleable_metadata->setCacheMaxAge(0);
-    $metadata_tests['[group:changed:since]'] = $bubbleable_metadata;
-
-    // Test to make sure that we generated something for each token.
-    $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
-
-    foreach ($tests as $token => $expected) {
-      $bubbleable_metadata = new BubbleableMetadata();
-      $output = $this->tokenService->replace($token, ['group' => $group], ['langcode' => $this->interfaceLanguage->getId()], $bubbleable_metadata);
-      $this->assertEquals($output, $expected, new FormattableMarkup('Group token %token replaced.', ['%token' => $token]));
-      $this->assertEquals($bubbleable_metadata, $metadata_tests[$token]);
-    }
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/GroupTypeCreateTest.php b/web/modules/group/tests/src/Kernel/GroupTypeCreateTest.php
deleted file mode 100644
index 706d41ed10..0000000000
--- a/web/modules/group/tests/src/Kernel/GroupTypeCreateTest.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel;
-
-/**
- * Tests the creation of group type entities.
- *
- * @coversDefaultClass \Drupal\group\Entity\GroupType
- * @group group
- */
-class GroupTypeCreateTest extends GroupKernelTestBase {
-
-  /**
-   * Tests special behavior during group type creation.
-   *
-   * @covers ::postSave
-   */
-  public function testCreate() {
-    // Check that the group type was created and saved properly.
-    /** @var \Drupal\group\Entity\GroupTypeInterface $group_type */
-    $group_type = $this->entityTypeManager
-      ->getStorage('group_type')
-      ->create([
-        'id' => 'dummy',
-        'label' => 'Dummy',
-        'description' => $this->randomMachineName(),
-      ]);
-
-    $this->assertTrue($group_type, 'Group type was created successfully.');
-    $this->assertEquals(SAVED_NEW, $group_type->save(), 'Group type was saved successfully.');
-
-    // Check that the special group roles were created.
-    $group_role_ids = [
-      $group_type->getAnonymousRoleId(),
-      $group_type->getOutsiderRoleId(),
-      $group_type->getMemberRoleId(),
-    ];
-
-    $group_roles = $this->entityTypeManager
-      ->getStorage('group_role')
-      ->loadMultiple($group_role_ids);
-
-    $this->assertEquals(3, count($group_roles), 'Three special roles were created.');
-
-    // Check that enforced plugins were installed.
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    $plugin_config = ['group_type_id' => 'dummy', 'id' => 'group_membership'];
-    $plugin = $this->pluginManager->createInstance('group_membership', $plugin_config);
-
-    $group_content_type = $this->entityTypeManager
-      ->getStorage('group_content_type')
-      ->load($plugin->getContentTypeConfigId());
-
-    $this->assertNotNull($group_content_type, 'Enforced plugins were installed on the group type.');
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/GroupTypeImportTest.php b/web/modules/group/tests/src/Kernel/GroupTypeImportTest.php
deleted file mode 100644
index 8529533726..0000000000
--- a/web/modules/group/tests/src/Kernel/GroupTypeImportTest.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel;
-
-/**
- * Tests the import or synchronization of group type entities.
- *
- * @coversDefaultClass \Drupal\group\Entity\GroupType
- * @group group
- */
-class GroupTypeImportTest extends GroupKernelTestBase {
-
-  /**
-   * Tests special behavior during group type import.
-   *
-   * @covers ::postSave
-   */
-  public function testImport() {
-    // Simulate config data to import.
-    $active = $this->container->get('config.storage');
-    $sync = $this->container->get('config.storage.sync');
-    $this->copyConfig($active, $sync);
-
-    // Manually add the 'import' group type to the synchronization directory.
-    $test_dir = __DIR__ . '/../../modules/group_test_config/sync';
-    $sync_dir = config_get_config_directory(CONFIG_SYNC_DIRECTORY);
-    $this->assertNotFalse(file_unmanaged_copy("$test_dir/group.type.import.yml", "$sync_dir/group.type.import.yml"), 'Copied the group type Yaml file to the sync dir.');
-
-    // Import the content of the sync directory.
-    $this->configImporter()->import();
-
-    // Check that the group type was created.
-    /** @var \Drupal\group\Entity\GroupTypeInterface $group_type */
-    $group_type = $this->entityTypeManager
-      ->getStorage('group_type')
-      ->load('import');
-
-    $this->assertNotNull($group_type, 'Import group type from sync was created.');
-
-    // Check that no special group roles were created.
-    $group_role_ids = [
-      $group_type->getAnonymousRoleId(),
-      $group_type->getOutsiderRoleId(),
-      $group_type->getMemberRoleId(),
-    ];
-
-    $group_roles = $this->entityTypeManager
-      ->getStorage('group_role')
-      ->loadMultiple($group_role_ids);
-
-    $this->assertEquals(0, count($group_roles), 'No special group roles were created.');
-
-    // Check that no enforced plugins were installed.
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    $plugin_config = ['group_type_id' => 'import', 'id' => 'group_membership'];
-    $plugin = $this->pluginManager->createInstance('group_membership', $plugin_config);
-
-    $group_content_type = $this->entityTypeManager
-      ->getStorage('group_content_type')
-      ->load($plugin->getContentTypeConfigId());
-
-    $this->assertNull($group_content_type, 'No enforced plugins were installed.');
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/GroupTypeInstallTest.php b/web/modules/group/tests/src/Kernel/GroupTypeInstallTest.php
deleted file mode 100644
index 687955429a..0000000000
--- a/web/modules/group/tests/src/Kernel/GroupTypeInstallTest.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel;
-
-/**
- * Tests the creation of group type entities during extension install.
- *
- * @coversDefaultClass \Drupal\group\Entity\GroupType
- * @group group
- */
-class GroupTypeInstallTest extends GroupKernelTestBase {
-
-  /**
-   * Tests special behavior during group type creation.
-   *
-   * @covers ::postSave
-   */
-  public function testInstall() {
-    // Check that the group type was installed properly.
-    /** @var \Drupal\group\Entity\GroupTypeInterface $group_type */
-    $group_type = $this->entityTypeManager
-      ->getStorage('group_type')
-      ->load('default');
-
-    $this->assertNotNull($group_type, 'Group type was loaded successfully.');
-
-    // Check that the special group roles give priority to the Yaml files.
-    $outsider = $group_type->getOutsiderRole();
-    $this->assertEquals(['join group', 'view group'], $outsider->getPermissions(), 'Outsider role was created from Yaml file.');
-
-    // Check that special group roles are being created without Yaml files.
-    /** @var \Drupal\group\Entity\GroupRoleInterface $group_role */
-    $group_role = $this->entityTypeManager
-      ->getStorage('group_role')
-      ->load($group_type->getAnonymousRoleId());
-
-    $this->assertNotNull($group_role, 'Anonymous role was created without a Yaml file.');
-
-    // Check that the enforced plugins give priority to the Yaml files.
-    /** @var \Drupal\group\Plugin\GroupContentEnablerInterface $plugin */
-    $plugin = $group_type->getContentPlugin('group_membership');
-    $config = $plugin->getConfiguration();
-
-    $this->assertEquals('99', $config['group_cardinality'], 'Enforced group_membership plugin was created from Yaml file.');
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/GroupTypeTest.php b/web/modules/group/tests/src/Kernel/GroupTypeTest.php
deleted file mode 100644
index bbd188073e..0000000000
--- a/web/modules/group/tests/src/Kernel/GroupTypeTest.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel;
-
-use Drupal\group\Entity\GroupTypeInterface;
-
-/**
- * Tests the general behavior of group type entities.
- *
- * @coversDefaultClass \Drupal\group\Entity\GroupType
- * @group group
- */
-class GroupTypeTest extends GroupKernelTestBase {
-
-  /**
-   * The 'default' group type from the group_test_config test module.
-   *
-   * @var \Drupal\group\Entity\GroupTypeInterface
-   */
-  protected $groupType;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->groupType = $this->entityTypeManager
-      ->getStorage('group_type')
-      ->load('default');
-  }
-
-  /**
-   * Tests the maximum ID length of a group type.
-   *
-   * @covers ::preSave
-   * @expectedException \Drupal\Core\Config\Entity\Exception\ConfigEntityIdLengthException
-   * @expectedExceptionMessageRegExp /Attempt to create a group type with an ID longer than \d+ characters: \w+\./
-   */
-  public function testMaximumIdLength() {
-    $this->entityTypeManager
-      ->getStorage('group_type')
-      ->create([
-        'id' => $this->randomMachineName(GroupTypeInterface::ID_MAX_LENGTH + 1),
-        'label' => 'Invalid ID length group type',
-        'description' => '',
-      ])
-      ->save();
-  }
-
-  /**
-   * Tests the retrieval of the collection of installed plugins.
-   *
-   * @covers ::getInstalledContentPlugins
-   */
-  public function testGetInstalledContentPlugins() {
-    $plugins = $this->groupType->getInstalledContentPlugins();
-    $this->assertInstanceOf('\Drupal\group\Plugin\GroupContentEnablerCollection', $plugins, 'Loaded the installed plugin collection.');
-    $this->assertCount(1, $plugins, 'Plugin collection has one plugin instance.');
-  }
-
-  /**
-   * Tests whether a group type can tell if it has a plugin installed.
-   *
-   * @covers ::hasContentPlugin
-   */
-  public function testHasContentPlugin() {
-    $this->assertTrue($this->groupType->hasContentPlugin('group_membership'), 'Found the group_membership plugin.');
-    $this->assertFalse($this->groupType->hasContentPlugin('fake_plugin_id'), 'Could not find the fake_plugin_id plugin.');
-  }
-
-  /**
-   * Tests the retrieval of an installed plugin.
-   *
-   * @covers ::getContentPlugin
-   */
-  public function testGetInstalledContentPlugin() {
-    $plugin = $this->groupType->getContentPlugin('group_membership');
-    $this->assertInstanceOf('\Drupal\group\Plugin\GroupContentEnablerInterface', $plugin, 'Loaded the group_membership plugin.');
-  }
-
-  /**
-   * Tests the retrieval of a non-existent plugin.
-   *
-   * @covers ::getContentPlugin
-   * @expectedException \Drupal\Component\Plugin\Exception\PluginNotFoundException
-   * @expectedExceptionMessage Plugin ID 'fake_plugin_id' was not found.
-   */
-  public function testGetNonExistentContentPlugin() {
-    $this->groupType->getContentPlugin('fake_plugin_id');
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/Views/GroupContentToEntityRelationshipTest.php b/web/modules/group/tests/src/Kernel/Views/GroupContentToEntityRelationshipTest.php
deleted file mode 100644
index 5bafb77b91..0000000000
--- a/web/modules/group/tests/src/Kernel/Views/GroupContentToEntityRelationshipTest.php
+++ /dev/null
@@ -1,157 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel\Views;
-
-use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
-use Drupal\views\Tests\ViewTestData;
-use Drupal\views\Views;
-
-/**
- * Tests the group_content_to_entity relationship handler.
- *
- * @see \Drupal\group\Plugin\views\relationship\GroupContentToEntity
- *
- * @group group
- */
-class GroupContentToEntityRelationshipTest extends ViewsKernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = ['group', 'field', 'text', 'group_test_config', 'user', 'group_test_plugin', 'group_test_views'];
-
-  /**
-   * Views used by this test.
-   *
-   * @var array
-   */
-  public static $testViews = ['test_group_content_to_entity_relationship'];
-
-  /**
-   * The entity type manager service.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp($import_test_views = TRUE) {
-    parent::setUp($import_test_views);
-
-    $this->entityTypeManager = $this->container->get('entity_type.manager');
-
-    $this->installConfig(['group', 'field', 'group_test_config']);
-    $this->installEntitySchema('user');
-    $this->installEntitySchema('group');
-    $this->installEntitySchema('group_type');
-    $this->installEntitySchema('group_content');
-    $this->installEntitySchema('group_content_type');
-
-    // Set the current user so group creation can rely on it.
-    $this->container->get('current_user')->setAccount($this->createUser());
-
-    // Enable the user_as_content plugin on the default group type.
-    /** @var \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface $storage */
-    $group_type = $this->entityTypeManager->getStorage('group_type')->load('default');
-    $storage = $this->entityTypeManager->getStorage('group_content_type');
-    $storage->createFromPlugin($group_type, 'user_as_content')->save();
-
-    ViewTestData::createTestViews(get_class($this), ['group_test_views']);
-  }
-
-  /**
-   * Creates a group.
-   *
-   * @param array $values
-   *   (optional) The values used to create the entity.
-   *
-   * @return \Drupal\group\Entity\Group
-   *   The created group entity.
-   */
-  protected function createGroup($values = []) {
-    $group = $this->entityTypeManager->getStorage('group')->create($values + [
-      'type' => 'default',
-      'label' => $this->randomMachineName(),
-    ]);
-    $group->enforceIsNew();
-    $group->save();
-    return $group;
-  }
-
-  /**
-   * Creates a user.
-   *
-   * @param array $values
-   *   (optional) The values used to create the entity.
-   *
-   * @return \Drupal\user\Entity\User
-   *   The created user entity.
-   */
-  protected function createUser($values = []) {
-    $account = $this->entityTypeManager->getStorage('user')->create($values + [
-      'name' => $this->randomMachineName(),
-      'status' => 1,
-    ]);
-    $account->enforceIsNew();
-    $account->save();
-    return $account;
-  }
-
-  /**
-   * Retrieves the results for this test's view.
-   *
-   * @return \Drupal\views\ResultRow[]
-   *   A list of view results.
-   */
-  protected function getViewResults() {
-    $view = Views::getView(reset($this::$testViews));
-    $view->setDisplay();
-
-    if ($view->preview()) {
-      return $view->result;
-    }
-
-    return [];
-  }
-
-  /**
-   * Tests that a regular user is not returned by the view.
-   */
-  public function testRegularUserIsNotListed() {
-    $this->createUser();
-    $this->assertEquals(0, count($this->getViewResults()), 'The view does not show regular users.');
-  }
-
-  /**
-   * Tests that a group's owner (default member) is returned by the view.
-   */
-  public function testGroupOwnerIsListed() {
-    $this->createGroup();
-    $this->assertEquals(1, count($this->getViewResults()), 'The view displays the user for the default member.');
-  }
-
-  /**
-   * Tests that an extra group member is returned by the view.
-   *
-   * @depends testGroupOwnerIsListed
-   */
-  public function testAddedMemberIsListed() {
-    $group = $this->createGroup();
-    $group->addMember($this->createUser());
-    $this->assertEquals(2, count($this->getViewResults()), 'The view displays the users for both the default and the added member.');
-  }
-
-  /**
-   * Tests that any other group content is not returned by the view.
-   *
-   * @depends testGroupOwnerIsListed
-   */
-  public function testOtherContentIsNotListed() {
-    $group = $this->createGroup();
-    $group->addContent($this->createUser(), 'user_as_content');
-    $this->assertEquals(1, count($this->getViewResults()), 'The view only displays the user for default member and not the one that was added as content.');
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/Views/GroupContentToEntityReverseRelationshipTest.php b/web/modules/group/tests/src/Kernel/Views/GroupContentToEntityReverseRelationshipTest.php
deleted file mode 100644
index 02ed5de958..0000000000
--- a/web/modules/group/tests/src/Kernel/Views/GroupContentToEntityReverseRelationshipTest.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel\Views;
-
-use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
-use Drupal\views\Tests\ViewTestData;
-use Drupal\views\Views;
-
-/**
- * Tests the group_content_to_entity_reverse relationship handler.
- *
- * @see \Drupal\group\Plugin\views\relationship\GroupContentToEntityReverse
- *
- * @group group
- */
-class GroupContentToEntityReverseRelationshipTest extends GroupContentToEntityRelationshipTest {
-
-  /**
-   * Views used by this test.
-   *
-   * @var array
-   */
-  public static $testViews = ['test_group_content_to_entity_reverse_relationship'];
-
-}
diff --git a/web/modules/group/tests/src/Kernel/Views/GroupIdArgumentTest.php b/web/modules/group/tests/src/Kernel/Views/GroupIdArgumentTest.php
deleted file mode 100644
index 2ffe55ca4a..0000000000
--- a/web/modules/group/tests/src/Kernel/Views/GroupIdArgumentTest.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel\Views;
-
-use Drupal\group\Entity\Group;
-use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
-use Drupal\user\Entity\User;
-use Drupal\views\Tests\ViewTestData;
-use Drupal\views\Views;
-
-/**
- * Tests the group_id argument handler.
- *
- * @see \Drupal\group\Plugin\views\argument\GroupId
- *
- * @group group
- */
-class GroupIdArgumentTest extends ViewsKernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = ['group', 'field', 'text', 'group_test_config', 'user', 'group_test_views'];
-
-  /**
-   * Views used by this test.
-   *
-   * @var array
-   */
-  public static $testViews = ['test_group_id_argument'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp($import_test_views = TRUE) {
-    parent::setUp($import_test_views);
-
-    $this->installConfig(['group', 'field', 'group_test_config']);
-    $this->installEntitySchema('user');
-    $this->installEntitySchema('group');
-    $this->installEntitySchema('group_type');
-    $this->installEntitySchema('group_content');
-    $this->installEntitySchema('group_content_type');
-
-    // Set the current user so group creation can rely on it.
-    $account = User::create(['name' => $this->randomString()]);
-    $account->save();
-    $this->container->get('current_user')->setAccount($account);
-
-    ViewTestData::createTestViews(get_class($this), ['group_test_views']);
-  }
-
-  /**
-   * Tests the group_id argument.
-   */
-  public function testGroupIdArgument() {
-    $view = Views::getView('test_group_id_argument');
-    $view->setDisplay();
-
-    /* @var \Drupal\group\Entity\GroupInterface $group1 */
-    $group1 = Group::create([
-      'type' => 'default',
-      'label' => $this->randomMachineName(),
-    ]);
-    $group1->save();
-
-    /* @var \Drupal\group\Entity\GroupInterface $group2 */
-    $group2 = Group::create([
-      'type' => 'default',
-      'label' => $this->randomMachineName(),
-    ]);
-    $group2->save();
-
-    $view->preview();
-    $this->assertEquals(2, count($view->result), 'Found the expected number of results.');
-
-    // Set the second group id as an argument.
-    $view->destroy();
-    $view->preview('default', [$group2->id()]);
-
-    // Verify that the title is overridden.
-    $this->assertEquals($group2->label(), $view->getTitle());
-
-    // Verify that the argument filtering works.
-    $this->assertEquals(1, count($view->result), 'Found the expected number of results.');
-    $this->assertEquals((string) $view->style_plugin->getField(0, 'id'), $group2->id(), 'Found the correct group id.');
-
-    // Verify that setting a non-existing id as argument results in no groups
-    // being shown.
-    $view->destroy();
-    $view->preview('default', [22]);
-    $this->assertEquals(0, count($view->result), 'Found the expected number of results.');
-  }
-
-}
diff --git a/web/modules/group/tests/src/Kernel/Views/GroupToGroupContentRelationshipTest.php b/web/modules/group/tests/src/Kernel/Views/GroupToGroupContentRelationshipTest.php
deleted file mode 100644
index c59a81bf04..0000000000
--- a/web/modules/group/tests/src/Kernel/Views/GroupToGroupContentRelationshipTest.php
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php
-
-namespace Drupal\Tests\group\Kernel\Views;
-
-use Drupal\Core\Session\AccountInterface;
-use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
-use Drupal\views\Tests\ViewTestData;
-use Drupal\views\Views;
-
-/**
- * Tests the group_to_group_content relationship handler.
- *
- * @see \Drupal\group\Plugin\views\argument\GroupId
- *
- * @group group
- */
-class GroupToGroupContentRelationshipTest extends ViewsKernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = ['group', 'field', 'text', 'group_test_config', 'user', 'group_test_plugin', 'group_test_views'];
-
-  /**
-   * Views used by this test.
-   *
-   * @var array
-   */
-  public static $testViews = ['test_group_to_group_content_relationship'];
-
-  /**
-   * The entity type manager service.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected $entityTypeManager;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp($import_test_views = TRUE) {
-    parent::setUp($import_test_views);
-
-    $this->entityTypeManager = $this->container->get('entity_type.manager');
-    $this->installTestConfiguration();
-    $this->setCurrentUser($this->createUser());
-
-    // Enable the 'user_as_content' plugin on the 'default' group type.
-    $group_type = $this->entityTypeManager->getStorage('group_type')->load('default');
-    /** @var \Drupal\group\Entity\Storage\GroupContentTypeStorageInterface $storage */
-    $storage = $this->entityTypeManager->getStorage('group_content_type');
-    $storage->createFromPlugin($group_type, 'user_as_content')->save();
-
-    ViewTestData::createTestViews(get_class($this), ['group_test_views']);
-  }
-
-  /**
-   * Installs the required configuration and schemas for this test.
-   */
-  protected function installTestConfiguration() {
-    $this->installConfig(['group', 'field', 'group_test_config']);
-    $this->installEntitySchema('user');
-    $this->installEntitySchema('group');
-    $this->installEntitySchema('group_type');
-    $this->installEntitySchema('group_content');
-    $this->installEntitySchema('group_content_type');
-  }
-
-  /**
-   * Set the current user so group creation can rely on it.
-   *
-   * @param \Drupal\Core\Session\AccountInterface $account
-   *   The account to set as the current user.
-   */
-  protected function setCurrentUser(AccountInterface $account) {
-    $this->container->get('current_user')->setAccount($account);
-  }
-
-  /**
-   * Creates a group.
-   *
-   * @param array $values
-   *   (optional) The values used to create the entity.
-   *
-   * @return \Drupal\group\Entity\Group
-   *   The created group entity.
-   */
-  protected function createGroup($values = []) {
-    $group = $this->entityTypeManager->getStorage('group')->create($values + [
-      'type' => 'default',
-      'label' => $this->randomMachineName(),
-    ]);
-    $group->enforceIsNew();
-    $group->save();
-    return $group;
-  }
-
-  /**
-   * Creates a user.
-   *
-   * @param array $values
-   *   (optional) The values used to create the entity.
-   *
-   * @return \Drupal\user\Entity\User
-   *   The created user entity.
-   */
-  protected function createUser($values = []) {
-    $account = $this->entityTypeManager->getStorage('user')->create($values + [
-      'name' => $this->randomMachineName(),
-      'status' => 1,
-    ]);
-    $account->enforceIsNew();
-    $account->save();
-    return $account;
-  }
-
-  /**
-   * Retrieves the results for this test's view.
-   *
-   * @return \Drupal\views\ResultRow[]
-   *   A list of view results.
-   */
-  protected function getViewResults() {
-    $view = Views::getView('test_group_to_group_content_relationship');
-    $view->setDisplay();
-
-    if ($view->preview()) {
-      return $view->result;
-    }
-
-    return [];
-  }
-
-  /**
-   * Tests that a group's owner (default member) is returned by the view.
-   */
-  public function testGroupOwnerIsListed() {
-    $this->assertEquals(0, count($this->getViewResults()), 'The view displays no members.');
-    $this->createGroup();
-    $this->assertEquals(1, count($this->getViewResults()), 'The view displays the default member.');
-  }
-
-  /**
-   * Tests that an extra group member is returned by the view.
-   *
-   * @depends testGroupOwnerIsListed
-   */
-  public function testAddedMemberIsListed() {
-    $group = $this->createGroup();
-    $group->addMember($this->createUser());
-    $this->assertEquals(2, count($this->getViewResults()), 'The view displays both the default and the added member.');
-  }
-
-  /**
-   * Tests that any other group content is not returned by the view.
-   *
-   * @depends testGroupOwnerIsListed
-   */
-  public function testOtherContentIsNotListed() {
-    $group = $this->createGroup();
-    $group->addContent($this->createUser(), 'user_as_content');
-    $this->assertEquals(1, count($this->getViewResults()), 'The view only displays the default member and not the user that was added as content.');
-  }
-
-}
-- 
GitLab