View source
<?php
declare (strict_types=1);
namespace Drupal\og;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\og\Entity\OgMembership;
use Drupal\user\UserInterface;
class MembershipManager implements MembershipManagerInterface {
protected $staticCache;
protected $entityTypeManager;
protected $groupAudienceHelper;
public function __construct(EntityTypeManagerInterface $entity_type_manager, OgGroupAudienceHelperInterface $group_audience_helper, CacheBackendInterface $cache) {
$this->entityTypeManager = $entity_type_manager;
$this->groupAudienceHelper = $group_audience_helper;
$this->staticCache = $cache;
}
public function getUserGroupIds($user_id, array $states = [
OgMembershipInterface::STATE_ACTIVE,
]) {
if ($user_id instanceof AccountInterface) {
trigger_error('Passing an account object is deprecated in og:8.1.0-alpha4 and is removed from og:8.1.0-beta1. Instead pass the user ID as an integer value. See https://github.com/Gizra/og/issues/542', E_USER_DEPRECATED);
$user_id = $user_id
->id();
}
$group_ids = [];
$memberships = $this
->getMemberships($user_id, $states);
foreach ($memberships as $membership) {
$group_ids[$membership
->getGroupEntityType()][] = $membership
->getGroupId();
}
return $group_ids;
}
public function getUserGroups($user_id, array $states = [
OgMembershipInterface::STATE_ACTIVE,
]) {
if ($user_id instanceof AccountInterface) {
trigger_error('Passing an account object is deprecated in og:8.1.0-alpha4 and is removed from og:8.1.0-beta1. Instead pass the user ID as an integer value. See https://github.com/Gizra/og/issues/542', E_USER_DEPRECATED);
$user_id = $user_id
->id();
}
$group_ids = $this
->getUserGroupIds($user_id, $states);
return $this
->loadGroups($group_ids);
}
public function getMemberships($user_id, array $states = [
OgMembershipInterface::STATE_ACTIVE,
]) {
if ($user_id instanceof AccountInterface) {
trigger_error('Passing an account object is deprecated in og:8.1.0-alpha4 and is removed from og:8.1.0-beta1. Instead pass the user ID as an integer value. See https://github.com/Gizra/og/issues/542', E_USER_DEPRECATED);
$user_id = $user_id
->id();
}
$states = $this
->prepareConditionArray($states, OgMembership::ALL_STATES);
$cid = [
__METHOD__,
$user_id,
implode('|', $states),
];
$cid = implode(':', $cid);
if (!($membership_ids = $this->staticCache
->get($cid)->data ?? [])) {
$query = $this->entityTypeManager
->getStorage('og_membership')
->getQuery()
->condition('uid', $user_id)
->condition('state', $states, 'IN');
$membership_ids = $query
->execute();
$this
->cacheMembershipIds($cid, $membership_ids);
}
return $this
->loadMemberships($membership_ids);
}
public function getMembership(EntityInterface $group, $user_id, array $states = [
OgMembershipInterface::STATE_ACTIVE,
]) {
if ($user_id instanceof AccountInterface) {
trigger_error('Passing an account object is deprecated in og:8.1.0-alpha4 and is removed from og:8.1.0-beta1. Instead pass the user ID as an integer value. See https://github.com/Gizra/og/issues/542', E_USER_DEPRECATED);
$user_id = $user_id
->id();
}
foreach ($this
->getMemberships($user_id, $states) as $membership) {
if ($membership
->getGroupEntityType() === $group
->getEntityTypeId() && $membership
->getGroupId() === $group
->id()) {
return $membership;
}
}
return NULL;
}
public function getUserGroupIdsByRoleIds($user_id, array $role_ids, array $states = [
OgMembershipInterface::STATE_ACTIVE,
], bool $require_all_roles = TRUE) : array {
if ($user_id instanceof AccountInterface) {
trigger_error('Passing an account object is deprecated in og:8.1.0-alpha4 and is removed from og:8.1.0-beta1. Instead pass the user ID as an integer value. See https://github.com/Gizra/og/issues/542', E_USER_DEPRECATED);
$user_id = $user_id
->id();
}
$memberships = $this
->getMemberships($user_id, $states);
$memberships = array_filter($memberships, function (OgMembershipInterface $membership) use ($role_ids, $require_all_roles) : bool {
$membership_roles_ids = $membership
->getRolesIds();
return $require_all_roles ? empty(array_diff($role_ids, $membership_roles_ids)) : !empty(array_intersect($membership_roles_ids, $role_ids));
});
$group_ids = [];
foreach ($memberships as $membership) {
$group_ids[$membership
->getGroupEntityType()][] = $membership
->getGroupId();
}
return $group_ids;
}
public function getUserGroupsByRoleIds($user_id, array $role_ids, array $states = [
OgMembershipInterface::STATE_ACTIVE,
], bool $require_all_roles = TRUE) : array {
if ($user_id instanceof AccountInterface) {
trigger_error('Passing an account object is deprecated in og:8.1.0-alpha4 and is removed from og:8.1.0-beta1. Instead pass the user ID as an integer value. See https://github.com/Gizra/og/issues/542', E_USER_DEPRECATED);
$user_id = $user_id
->id();
}
$group_ids = $this
->getUserGroupIdsByRoleIds($user_id, $role_ids, $states, $require_all_roles);
return $this
->loadGroups($group_ids);
}
public function getGroupMembershipIdsByRoleNames(EntityInterface $group, array $role_names, array $states = [
OgMembershipInterface::STATE_ACTIVE,
]) {
if (empty($role_names)) {
throw new \InvalidArgumentException('The array of role names should not be empty.');
}
$retrieve_all_memberships = FALSE;
if (in_array(OgRoleInterface::AUTHENTICATED, $role_names)) {
$retrieve_all_memberships = TRUE;
$role_names = [
OgRoleInterface::AUTHENTICATED,
];
}
$role_names = $this
->prepareConditionArray($role_names);
$states = $this
->prepareConditionArray($states, OgMembership::ALL_STATES);
$cid = [
__METHOD__,
$group
->getEntityTypeId(),
$group
->id(),
implode('|', $role_names),
implode('|', $states),
];
$cid = implode(':', $cid);
if (!($membership_ids = $this->staticCache
->get($cid)->data ?? [])) {
$entity_type_id = $group
->getEntityTypeId();
$query = $this->entityTypeManager
->getStorage('og_membership')
->getQuery()
->condition('entity_type', $entity_type_id)
->condition('entity_id', $group
->id())
->condition('state', $states, 'IN');
if (!$retrieve_all_memberships) {
$bundle_id = $group
->bundle();
$role_ids = array_map(function ($role_name) use ($entity_type_id, $bundle_id) {
return implode('-', [
$entity_type_id,
$bundle_id,
$role_name,
]);
}, $role_names);
$query
->condition('roles', $role_ids, 'IN');
}
$membership_ids = $query
->execute();
$this
->cacheMembershipIds($cid, $membership_ids);
}
return $membership_ids;
}
public function getGroupMembershipsByRoleNames(EntityInterface $group, array $role_names, array $states = [
OgMembershipInterface::STATE_ACTIVE,
]) {
$ids = $this
->getGroupMembershipIdsByRoleNames($group, $role_names, $states);
return $this
->loadMemberships($ids);
}
public function createMembership(EntityInterface $group, UserInterface $user, $membership_type = OgMembershipInterface::TYPE_DEFAULT) {
$membership = OgMembership::create([
'type' => $membership_type,
]);
$membership
->setOwner($user)
->setGroup($group);
return $membership;
}
public function getGroupIds(EntityInterface $entity, $group_type_id = NULL, $group_bundle = NULL) {
if ($entity instanceof UserInterface) {
throw new \InvalidArgumentException('\\Drupal\\og\\MembershipManager::getGroupIds() cannot be used for user entities. Use \\Drupal\\og\\MembershipManager::getUserGroups() instead.');
}
if (!$this->groupAudienceHelper
->hasGroupAudienceField($entity
->getEntityTypeId(), $entity
->bundle())) {
throw new \InvalidArgumentException('Can only retrieve group IDs for group content entities.');
}
$cid = [
__METHOD__,
$entity
->getEntityTypeId(),
$entity
->id(),
$group_type_id,
$group_bundle,
];
$cid = implode(':', $cid);
if ($group_ids = $this->staticCache
->get($cid)->data ?? []) {
return $group_ids;
}
$group_ids = [];
$tags = $entity
->getCacheTagsToInvalidate();
$fields = $this->groupAudienceHelper
->getAllGroupAudienceFields($entity
->getEntityTypeId(), $entity
->bundle(), $group_type_id, $group_bundle);
foreach ($fields as $field) {
$target_type_id = $field
->getFieldStorageDefinition()
->getSetting('target_type');
$target_type_definition = $this->entityTypeManager
->getDefinition($target_type_id);
if (!empty($group_type_id) && $group_type_id !== $target_type_id) {
continue;
}
$values = $entity
->get($field
->getName())
->getValue();
if (empty($values[0])) {
continue;
}
$target_ids = array_filter(array_map(function ($value) {
return $value['target_id'] ?? NULL;
}, $entity
->get($field
->getName())
->getValue()));
if (empty($target_ids)) {
continue;
}
$entity_type = $this->entityTypeManager
->getDefinition($target_type_id);
$query = $this->entityTypeManager
->getStorage($target_type_id)
->getQuery()
->accessCheck(FALSE)
->condition($entity_type
->getKey('id'), $target_ids, 'IN');
if (!empty($group_bundle)) {
$query
->condition($entity_type
->getKey('bundle'), $group_bundle);
}
$tags = Cache::mergeTags($target_type_definition
->getListCacheTags(), $tags);
$group_ids = NestedArray::mergeDeep($group_ids, [
$target_type_id => $query
->execute(),
]);
}
$this->staticCache
->set($cid, $group_ids, Cache::PERMANENT, $tags);
return $group_ids;
}
public function getGroups(EntityInterface $entity, $group_type_id = NULL, $group_bundle = NULL) {
$group_ids = $this
->getGroupIds($entity, $group_type_id, $group_bundle);
return $this
->loadGroups($group_ids);
}
public function getGroupCount(EntityInterface $entity, $group_type_id = NULL, $group_bundle = NULL) {
return array_reduce($this
->getGroupIds($entity, $group_type_id, $group_bundle), function ($carry, $item) {
return $carry + count($item);
}, 0);
}
public function getGroupContentIds(EntityInterface $entity, array $entity_types = []) {
$group_content = [];
$query = $this->entityTypeManager
->getStorage('field_storage_config')
->getQuery()
->condition('type', OgGroupAudienceHelperInterface::GROUP_REFERENCE);
if ($entity_types) {
$query
->condition('entity_type', $entity_types, 'IN');
}
$storage = $this->entityTypeManager
->getStorage('field_storage_config');
$fields = array_filter($storage
->loadMultiple($query
->execute()), function (FieldStorageConfigInterface $field) use ($entity) {
$type_matches = $field
->getSetting('target_type') === $entity
->getEntityTypeId();
$bundle_matches = empty($field
->getSetting('target_bundles')) || in_array($entity
->bundle(), $field
->getSetting('target_bundles'));
return $type_matches && $bundle_matches;
});
foreach ($fields as $field) {
$group_content_entity_type = $field
->getTargetEntityTypeId();
if (!isset($group_content[$group_content_entity_type])) {
$group_content[$group_content_entity_type] = [];
}
$results = $this->entityTypeManager
->getStorage($group_content_entity_type)
->getQuery()
->condition($field
->getName() . '.target_id', $entity
->id())
->execute();
$group_content[$group_content_entity_type] = array_merge($group_content[$group_content_entity_type], $results);
}
return $group_content;
}
public function isMember(EntityInterface $group, $user_id, array $states = [
OgMembershipInterface::STATE_ACTIVE,
]) {
if ($user_id instanceof AccountInterface) {
trigger_error('Passing an account object is deprecated in og:8.1.0-alpha4 and is removed from og:8.1.0-beta1. Instead pass the user ID as an integer value. See https://github.com/Gizra/og/issues/542', E_USER_DEPRECATED);
$user_id = $user_id
->id();
}
$group_ids = $this
->getUserGroupIds($user_id, $states);
$entity_type_id = $group
->getEntityTypeId();
return !empty($group_ids[$entity_type_id]) && in_array($group
->id(), $group_ids[$entity_type_id]);
}
public function isMemberPending(EntityInterface $group, $user_id) {
if ($user_id instanceof AccountInterface) {
trigger_error('Passing an account object is deprecated in og:8.1.0-alpha4 and is removed from og:8.1.0-beta1. Instead pass the user ID as an integer value. See https://github.com/Gizra/og/issues/542', E_USER_DEPRECATED);
$user_id = $user_id
->id();
}
return $this
->isMember($group, $user_id, [
OgMembershipInterface::STATE_PENDING,
]);
}
public function isMemberBlocked(EntityInterface $group, $user_id) {
if ($user_id instanceof AccountInterface) {
trigger_error('Passing an account object is deprecated in og:8.1.0-alpha4 and is removed from og:8.1.0-beta1. Instead pass the user ID as an integer value. See https://github.com/Gizra/og/issues/542', E_USER_DEPRECATED);
$user_id = $user_id
->id();
}
return $this
->isMember($group, $user_id, [
OgMembershipInterface::STATE_BLOCKED,
]);
}
protected function prepareConditionArray(array $value, ?array $default = NULL) {
if (empty($value) && $default !== NULL) {
$value = $default;
}
sort($value);
return array_unique($value);
}
protected function loadGroups(array $group_ids) : array {
$groups = [];
foreach ($group_ids as $entity_type => $ids) {
$groups[$entity_type] = $this->entityTypeManager
->getStorage($entity_type)
->loadMultiple($ids);
}
return $groups;
}
protected function cacheMembershipIds($cid, array $membership_ids) {
$tags = Cache::buildTags('og_membership', $membership_ids);
$tags = Cache::mergeTags([
'og_membership_list',
], $tags);
$this->staticCache
->set($cid, $membership_ids, Cache::PERMANENT, $tags);
}
protected function loadMemberships(array $ids) {
if (empty($ids)) {
return [];
}
return $this->entityTypeManager
->getStorage('og_membership')
->loadMultiple($ids);
}
}