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

Issue #3382831 by kristiaanvandeneynde: Allow shared bundle classes for group...

Issue #3382831 by kristiaanvandeneynde: Allow shared bundle classes for group relationships using the same plugin
parent f23e0595
No related branches found
No related tags found
4 merge requests!207Issue #3497467 by vasyapledov: Take gid from the route instead of Group for cache context 'route.group',!193Issue #3304728 by kristiaanvandeneynde: Add member page missing due to...,!142Issue #3304728 by kristiaanvandeneynde: Add member page missing due to...,!102Issue #3382831: Allow shared bundle classes for group relationships using the same plugin
Showing with 202 additions and 0 deletions
<?php
namespace Drupal\group\Entity;
/**
* Base class for shared bundle classes.
*
* This class takes care of the static methods that would otherwise crash when
* you have one class serving multiple bundles.
*/
class SharedBundleClassBase extends GroupRelationship {
/**
* {@inheritdoc}
*/
public static function create(array $values = []) {
return \Drupal::entityTypeManager()->getStorage('group_content')->create($values);
}
/**
* {@inheritdoc}
*/
public static function load($id) {
return \Drupal::entityTypeManager()->getStorage('group_content')->load($id);
}
/**
* {@inheritdoc}
*/
public static function loadMultiple(array $ids = NULL) {
return \Drupal::entityTypeManager()->getStorage('group_content')->loadMultiple($ids);
}
}
......@@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\group\Entity\GroupInterface;
use Drupal\group\Entity\GroupRelationshipInterface;
use Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -79,6 +80,32 @@ class GroupRelationshipStorage extends SqlContentEntityStorage implements GroupR
parent::restore($entity);
}
/**
* {@inheritdoc}
*/
public function getEntityClass(?string $bundle = NULL): string {
$entity_class = parent::getEntityClass($bundle);
if ($bundle) {
$plugin_id = $this->entityTypeManager
->getStorage('group_content_type')
->load($bundle)
->getPluginId();
$group_relation_type = $this->pluginManager->getDefinition($plugin_id);
assert($group_relation_type instanceof GroupRelationTypeInterface);
if ($shared_bundle_class = $group_relation_type->getSharedBundleClass()) {
// No specific bundle class, so it's safe to return the shared one.
if ($entity_class === parent::getEntityClass()) {
return $shared_bundle_class;
}
}
}
return $entity_class;
}
/**
* {@inheritdoc}
*/
......
......@@ -67,6 +67,22 @@ class GroupRelationType extends PluginDefinition implements GroupRelationTypeInt
*/
protected $entity_bundle = FALSE;
/**
* (optional) The bundle class for all relationships using this plugin.
*
* If you make sure that your shared class puts all of its functionality in a
* trait and has its own interface, then it should be easy for others to still
* create a regular bundle class and get your functionality by simply using
* your trait and interface.
*
* Shared bundle classes should use \Drupal\group\Entity\SharedBundleClassBase
* as their base class so that some common Drupal core pitfalls are taken care
* of for them.
*
* @var string|false
*/
protected $shared_bundle_class = FALSE;
/**
* (optional) Whether the supported entity type is config.
*
......@@ -220,6 +236,13 @@ class GroupRelationType extends PluginDefinition implements GroupRelationTypeInt
return $this->entity_bundle;
}
/**
* {@inheritdoc}
*/
public function getSharedBundleClass() {
return $this->shared_bundle_class;
}
/**
* {@inheritdoc}
*/
......
......@@ -94,6 +94,14 @@ interface GroupRelationTypeInterface extends PluginDefinitionInterface, Derivabl
*/
public function getEntityBundle();
/**
* Returns the shared bundle class.
*
* @return string|false
* The shared bundle class or FALSE if none was defined.
*/
public function getSharedBundleClass();
/**
* Returns whether this plugin deals with a config entity type.
*
......
<?php
/**
* @file
* Helper module for the Group plugin tests.
*/
/**
* Implements hook_entity_bundle_info_alter().
*/
function group_test_plugin_entity_bundle_info_alter(&$bundles) {
if (!empty($GLOBALS['specific_bundle_id'])) {
$bundles['group_content'][$GLOBALS['specific_bundle_id']]['class'] = '\Drupal\group_test_plugin\Entity\GroupedUserSpecific';
}
}
<?php
namespace Drupal\group_test_plugin\Entity;
use Drupal\group\Entity\SharedBundleClassBase;
/**
* Shared bundle class for a UserAsContentSharedBundleClass group relationship.
*/
class GroupedUser extends SharedBundleClassBase {
}
<?php
namespace Drupal\group_test_plugin\Entity;
use Drupal\group\Entity\GroupRelationship;
/**
* Specific bundle class for a UserAsContentSharedBundleClass group relationship.
*/
class GroupedUserSpecific extends GroupRelationship {
}
<?php
namespace Drupal\group_test_plugin\Plugin\Group\Relation;
use Drupal\group\Plugin\Group\Relation\GroupRelationBase;
/**
* Provides a group relation type for users.
*
* @GroupRelationType(
* id = "user_as_content_shared_bundle_class",
* label = @Translation("Group user"),
* description = @Translation("Relates users to groups without making them members."),
* entity_type_id = "user",
* pretty_path_key = "user_shared_bundle_class",
* shared_bundle_class = "Drupal\group_test_plugin\Entity\GroupedUser",
* reference_label = @Translation("Username"),
* reference_description = @Translation("The name of the user you want to relate to the group"),
* admin_permission = "administer user_as_content_shared_bundle_class"
* )
*/
class UserAsContentSharedBundleClass extends GroupRelationBase {
}
......@@ -64,6 +64,7 @@ class GroupPermissionHandlerTest extends GroupKernelTestBase {
$expected += count($this->pluginManager->getPermissionProvider('entity_test_as_content')->buildPermissions());
$expected += count($this->pluginManager->getPermissionProvider('group_as_content')->buildPermissions());
$expected += count($this->pluginManager->getPermissionProvider('user_as_content')->buildPermissions());
$expected += count($this->pluginManager->getPermissionProvider('user_as_content_shared_bundle_class')->buildPermissions());
$expected += count($this->pluginManager->getPermissionProvider('node_as_content:article')->buildPermissions());
$expected += count($this->pluginManager->getPermissionProvider('node_as_content:page')->buildPermissions());
$expected += count($this->pluginManager->getPermissionProvider('node_type_as_content')->buildPermissions());
......
......@@ -323,4 +323,53 @@ class GroupRelationshipStorageTest extends GroupKernelTestBase {
$this->assertCount(1, $this->storage->loadByPluginId('group_membership'), 'Managed to load the group creator membership by plugin ID.');
}
/**
* Tests that shared bundle classes work.
*
* @covers ::getEntityClass
*/
public function testSharedBundleClass() {
$group_type_none = $this->createGroupType();
$group_type_shared = $this->createGroupType();
$group_type_specific = $this->createGroupType();
$account = $this->createUser();
// Enable the test plugins on the test group types.
$storage = $this->entityTypeManager->getStorage('group_content_type');
assert($storage instanceof GroupRelationshipTypeStorageInterface);
$storage->createFromPlugin($group_type_none, 'user_as_content')->save();
$storage->createFromPlugin($group_type_shared, 'user_as_content_shared_bundle_class')->save();
$storage->createFromPlugin($group_type_specific, 'user_as_content_shared_bundle_class')->save();
// Verify that the group types use the expected entity class.
$group_relationship_none = $this->storage->createForEntityInGroup($account, $this->createGroup(['type' => $group_type_none->id()]), 'user_as_content');
$group_relationship_shared = $this->storage->createForEntityInGroup($account, $this->createGroup(['type' => $group_type_shared->id()]), 'user_as_content_shared_bundle_class');
$group_relationship_specific = $this->storage->createForEntityInGroup($account, $this->createGroup(['type' => $group_type_specific->id()]), 'user_as_content_shared_bundle_class');
$this->assertInstanceOf('\Drupal\group\Entity\GroupRelationship', $group_relationship_none, 'Regular entity class detected when no specific or shared bundle class was present.');
$this->assertInstanceOf('\Drupal\group_test_plugin\Entity\GroupedUser', $group_relationship_shared, 'Shared bundle class detected when no specific bundle class was present.');
$this->assertInstanceOf('\Drupal\group_test_plugin\Entity\GroupedUser', $group_relationship_specific, 'Shared bundle class detected when no specific bundle class was present.');
// Enable a specific bundle class.
$GLOBALS['specific_bundle_id'] = $storage->getRelationshipTypeId($group_type_specific->id(), 'user_as_content_shared_bundle_class');
$this->entityTypeManager->clearCachedDefinitions();
\Drupal::service('entity_type.bundle.info')->clearCachedBundles();
// Verify again, checking that the specific bundle class takes precedence.
$group_relationship_none = $this->storage->createForEntityInGroup($account, $this->createGroup(['type' => $group_type_none->id()]), 'user_as_content');
$group_relationship_shared = $this->storage->createForEntityInGroup($account, $this->createGroup(['type' => $group_type_shared->id()]), 'user_as_content_shared_bundle_class');
$group_relationship_specific = $this->storage->createForEntityInGroup($account, $this->createGroup(['type' => $group_type_specific->id()]), 'user_as_content_shared_bundle_class');
$this->assertInstanceOf('\Drupal\group\Entity\GroupRelationship', $group_relationship_none, 'Regular entity class detected when no specific or shared bundle class was present.');
$this->assertInstanceOf('\Drupal\group_test_plugin\Entity\GroupedUser', $group_relationship_shared, 'Shared bundle class detected when no specific bundle class was present.');
$this->assertInstanceOf('\Drupal\group_test_plugin\Entity\GroupedUserSpecific', $group_relationship_specific, 'Specific bundle class detected when specific bundle class was present.');
// Enable specific bundle class for the plugin without shared bundle class.
$GLOBALS['specific_bundle_id'] = $storage->getRelationshipTypeId($group_type_none->id(), 'user_as_content');
$this->entityTypeManager->clearCachedDefinitions();
\Drupal::service('entity_type.bundle.info')->clearCachedBundles();
// Verify again, checking that the specific bundle class works.
$group_relationship_none = $this->storage->createForEntityInGroup($account, $this->createGroup(['type' => $group_type_none->id()]), 'user_as_content');
$this->assertInstanceOf('\Drupal\group_test_plugin\Entity\GroupedUserSpecific', $group_relationship_none, 'Specific bundle class detected when no shared bundle class was present.');
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment