On this page
- General information
- Group relation plugin
- Database structure
- API changes
- GroupRelationshipType (GroupContentType in 1.0)
- GroupRelationshipStorage (GroupContentStorage in 1.0)
- GroupRelationshipTypeStorage (GroupContentTypeStorage in 1.0)
- GroupRelationBase (GroupContentEnablerBase in 1.0)
- GroupRelationshipType (GroupContentType in 1.0)
- Group
- GroupType
- GroupRelationship (GroupContent in 1.0)
- GroupRelationTypeManager (GroupContentEnablerManager in 1.0)
Upgrading from v1 to v2
This documentation needs review. See "Help improve this page" in the sidebar.
General information
Group module 2.0 is almost there and it provides a quite a lot of new changes. A new version contains many API changes and new features In this guide we will review the main steps to be prepared for the upgrade.
For more details please consult the next pages:
and
Group 2.0 now depends on the flexible_permissions module, which lets us use a new central service for permission handling instead of relying on Entity API anymore. This makes permission handling much faster as we don't need to alter queries anymore.
The system of plugins has been renamed and reworked.
The roles system has been updated: by default Group no longer provides any roles, and we can remove any role we want.
Config entities can now be part of a group without the need for custom patches!
Access checks are reworked and Group will handle access only to known operations. So, if you have a custom operation, Group will no longer automatically forbid it.
Group relation plugin
First you need to rename and to move your plugin to a new location. Content enabler plugin was renamed to Group relation plugin. Now plugin is located in src/Plugin/Group/Relation/[YourRelationPlugin].php
In Group 2.0 plugin id will stay "group_content", but in Group 3.0 the plugin id will be replaced with "group_relationship"
Group relation plugin uses handlers to provide it's main features. The most of methods of Group enabler plugin were moved to separate handler classes. Each handler can be defined as a service, but we need to follow specific naming convention.
group.relation_handler.[HANDLER_TYPE].[YOUR_PLUGIN_ID]an example for grequest module defining entity reference handler service:
group.relation_handler.entity_reference.group_membership_request:
class: 'Drupal\grequest\Plugin\Group\RelationHandler\GroupMembershipRequestEntityReference'
arguments: [ '@group.relation_handler.entity_reference' ]
shared: false* shared: false means that every time a new instance of handler will be created. It is requirement to make a plugin work with it's own instance of the handler. As of Group 2.3.1 and 3.3.1 you no longer need to specify this yourself.
The Groups module comes with the following handlers:
access_controlentity_referenceoperation_providerpermission_providerpost_installui_text_provider
Group enabler plugin handles this functionality in the methods:
| Group Relation Handler (Group 2.0) | Group enabler plugin methods (1.0) |
| access_control | checkAccess |
| entity_reference | getEntityReferenceSettings |
| operation_provider |
getOperations |
| permission_provider | permission provider is defined as separate class |
| post_install |
postInstall |
| ui_text_provider |
If you have a custom logic in this methods please consider to move them to a separate handler class.
All handlers services are located in src/Plugin/Group/RelationHandler/
Keep in mind, by default Group module already has default handlers and we need to define a new one only in the situation when we need to override default behavior in other cases default one will work just perfect and you don't need to do anything.
More information about handlers can be found in this Presentation
Database structure
The table structure of group content tables has been updated, but you do not need to do anything here. The update hooks will update the table for you. This is only as a reference for developers who used to target the database tables directly.
Group 1.0 - group_content_field_data table
CREATE TABLE `group_content_field_data` (
`id` int(10) UNSIGNED NOT NULL,
`type` varchar(32) CHARACTER SET ascii NOT NULL COMMENT 'The ID of the target entity.',
`langcode` varchar(12) CHARACTER SET ascii NOT NULL,
`gid` int(10) UNSIGNED DEFAULT NULL COMMENT 'The ID of the target entity.',
`entity_id` int(10) UNSIGNED DEFAULT NULL COMMENT 'The ID of the target entity.',
`label` varchar(255) DEFAULT NULL,
`uid` int(10) UNSIGNED DEFAULT NULL COMMENT 'The ID of the target entity.',
`created` int(11) DEFAULT NULL,
`changed` int(11) DEFAULT NULL,
`default_langcode` tinyint(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='The data table for group_content entities.';Group 2.0 - group_relationship_field_data
CREATE TABLE `group_relationship_field_data` (
`id` int(10) UNSIGNED NOT NULL,
`type` varchar(32) CHARACTER SET ascii NOT NULL COMMENT 'The ID of the target entity.',
`langcode` varchar(12) CHARACTER SET ascii NOT NULL,
`uid` int(10) UNSIGNED NOT NULL COMMENT 'The ID of the target entity.',
`gid` int(10) UNSIGNED NOT NULL COMMENT 'The ID of the target entity.',
`entity_id` int(10) UNSIGNED NOT NULL COMMENT 'The ID of the target entity.',
`label` varchar(255) DEFAULT NULL,
`created` int(11) DEFAULT NULL,
`changed` int(11) DEFAULT NULL,
`plugin_id` varchar(64) NOT NULL,
`group_type` varchar(32) CHARACTER SET ascii DEFAULT NULL COMMENT 'The ID of the target entity.',
`default_langcode` tinyint(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='The data table for group_content entities.';* if you create group relationship (former group content) programmatically you do not have to add group_type and plugin_id manually, this will be filled out for you based on the provided bundle.
API changes
| Class name Group 1.0 | Class name Group 2.0 |
Drupal\group\Plugin\
GroupContentEnablerInterface |
Drupal\group\Plugin\Group\Relation\ GroupRelationInterface |
Drupal\group\Plugin\ GroupContentEnablerBase |
Drupal\group\Plugin\Group\Relation\ GroupRelationBase |
Drupal\group\Entity\ GroupContent |
Drupal\group\Entity\ GroupRelationship |
Drupal\group\Entity\ GroupContentInterface |
Drupal\group\Entity\GroupRelationshipInterface |
Drupal\group\Entity\ GroupContentType |
Drupal\group\Entity\ GroupRelationshipType |
Drupal\group\Entity\ GroupContentTypeInterface |
Drupal\group\Entity\ GroupRelationshipTypeInterface |
Drupal\group\Entity\Storage\ GroupContentStorage |
Drupal\group\Entity\Storage\ GroupRelationshipStorage |
Drupal\group\Entity\Storage\ GroupContentStorageInterface |
Drupal\group\Entity\Storage\ GroupRelationshipStorageInterface |
Drupal\group\Entity\Storage\ GroupContentTypeStorage |
Drupal\group\Entity\Storage\ GroupRelationshipTypeStorage |
Drupal\group\Entity\Storage\ GroupContentTypeStorageInterface |
Drupal\group\Entity\Storage\ GroupRelationshipTypeStorageInterface |
* In the table above presented the most used classes in the custom modules. The rest of entity related classes can be renamed by replacing GroupContent to GroupRelationship
GroupRelationshipType (GroupContentType in 1.0)
| method Group 1.0 | method Group 2.0 |
loadByContentPluginId |
loadByPluginId |
updateContentPlugin |
updatePlugin |
GroupRelationshipStorage (GroupContentStorage in 1.0)
| method Group 1.0 | method Group 2.0 |
loadByContentPluginId |
loadByPluginId |
public function loadByGroup(GroupInterface $group, $plugin_id = NULL, $filters = []); |
public function loadByGroup(GroupInterface $group, $plugin_id = NULL); Additional filters are not supported anymore. Use loadByEntityAndGroup instead to filter by a specific entity. |
GroupRelationshipTypeStorage (GroupContentTypeStorage in 1.0)
| method Group 1.0 | method Group 2.0 |
loadByContentPluginId |
loadByPluginId |
GroupRelationBase (GroupContentEnablerBase in 1.0)
| method Group 1.0 | method Group 2.0 |
getContentTypeLabel |
use GroupRelationType->getLabel instead |
checkAccess |
removed and handled in access_control handler |
createAccess |
removed and handled in access_control handler |
createEntityAccess |
removed and handled in access_control handler |
getContentLabel |
removed and handled in ui_text_provider handler |
getContentTypeConfigId |
removed and handled in relationship type storage |
getContentTypeDescription |
removed and handled in ui_text_provider handler |
getOperations |
removed and handled in operation_provider relation handler |
postInstall |
removed and handled in post_install relation handler |
getEntityReferenceSettings |
removed and handled in entity_reference relation handler |
getEntityBundle |
moved to GroupRelationType class |
getGroupOperations |
removed and handled in operation_provider relation handler |
getEntityTypeId |
moved to GroupRelationType class |
definesEntityAccess |
moved to GroupRelationType class |
| getDescription | moved to GroupRelationType class |
getEntityReferenceLabel |
moved to GroupRelationType class |
getEntityReferenceDescription |
moved to GroupRelationType class |
getEntityType |
removed! |
getGroupOperationsCacheableMetadata |
removed and handled in operation_provider relation handler |
getPermissions |
removed and handled in permission_provider handler |
getPrettyPathKey |
moved to GroupRelationType class |
getProvider |
moved to GroupRelationType class |
getTargetEntityPermissions |
removed! |
isCodeOnly |
moved to GroupRelationType class |
isEnforced |
moved to GroupRelationType class |
updateAccess |
removed! |
viewAccess |
removed! |
GroupRelationshipType (GroupContentType in 1.0)
| method Group 1.0 | method Group 2.0 |
getContentEnablerManager |
getGroupRelationTypeManager |
getContentPlugin |
getPlugin |
getContentPluginId |
getPluginId |
loadByContentPluginId |
loadByPluginId |
updateContentPlugin |
updatePlugin |
Group
| method Group 1.0 | method Group 2.0 |
getContent |
getRelationships Additional filters are not supported anymore. Use getRelationshipsByEntity instead to filter by a specific entity. |
getContentByEntityId |
getRelationshipsByEntity |
getContentEntities |
getRelatedEntities |
addContent |
addRelationship |
GroupType
| method Group 1.0 | method Group 2.0 |
getContentEnablerManager |
getGroupRelationTypeManager |
getContentPlugin |
getPlugin |
hasContentPlugin |
hasPlugin |
getInstalledContentPlugins |
getInstalledPlugins |
getAnonymousRole |
removed! |
getAnonymousRoleId |
removed! |
getOutsiderRole |
removed! |
getOutsiderRoleId |
removed! |
getMemberRole |
removed! |
getMemberRoleId |
removed! |
| getGroupRoleSynchronizer | removed! |
GroupRelationship (GroupContent in 1.0)
| method Group 1.0 | method Group 2.0 |
getContentPlugin |
getPluginId |
loadByContentPluginId |
loadByPluginId |
getGroupContentType |
getRelationshipType |
GroupRelationTypeManager (GroupContentEnablerManager in 1.0)
| method Group 1.0 | method Group 2.0 |
getInstalled |
GroupTypeInterface parameter is not optional anymore |
getInstalledIds |
GroupTypeInterface parameter is not optional anymore |
hasHandler |
Removed |
getGroupContentTypeStorage |
getRelationshipTypeStorage |
getAll |
Removed |
getVanillaInstalled |
Removed |
getGroupTypeInstalled |
Removed |
getGroupContentTypeIds |
getRelationshipTypeIds |
getPluginGroupContentTypeMap |
getPluginGroupRelationshipTypeMap |
getCachedPluginGroupContentTypeMap |
getCachedPluginGroupRelationshipTypeMap |
setCachedPluginGroupContentTypeMap |
setCachedPluginGroupRelationshipTypeMap |
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion