View source
<?php
declare (strict_types=1);
namespace Drupal\og\EventSubscriber;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\og\Event\DefaultRoleEventInterface;
use Drupal\og\Event\GroupContentEntityOperationAccessEventInterface;
use Drupal\og\Event\OgAdminRoutesEventInterface;
use Drupal\og\Event\PermissionEventInterface;
use Drupal\og\GroupContentOperationPermission;
use Drupal\og\GroupPermission;
use Drupal\og\OgAccess;
use Drupal\og\OgAccessInterface;
use Drupal\og\OgRoleInterface;
use Drupal\og\PermissionManagerInterface;
use Drupal\user\EntityOwnerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OgEventSubscriber implements EventSubscriberInterface {
use StringTranslationTrait;
protected $permissionManager;
protected $entityTypeManager;
protected $entityTypeBundleInfo;
protected $ogAccess;
public function __construct(PermissionManagerInterface $permission_manager, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, OgAccessInterface $og_access) {
$this->permissionManager = $permission_manager;
$this->entityTypeManager = $entity_type_manager;
$this->entityTypeBundleInfo = $entity_type_bundle_info;
$this->ogAccess = $og_access;
}
public static function getSubscribedEvents() {
return [
PermissionEventInterface::EVENT_NAME => [
[
'provideDefaultOgPermissions',
10,
],
[
'provideDefaultNodePermissions',
],
],
DefaultRoleEventInterface::EVENT_NAME => [
[
'provideDefaultRoles',
],
],
OgAdminRoutesEventInterface::EVENT_NAME => [
[
'provideOgAdminRoutes',
],
],
GroupContentEntityOperationAccessEventInterface::EVENT_NAME => [
[
'checkGroupContentEntityOperationAccess',
],
],
];
}
public function provideDefaultOgPermissions(PermissionEventInterface $event) {
$event
->setPermissions([
new GroupPermission([
'name' => OgAccess::ADMINISTER_GROUP_PERMISSION,
'title' => $this
->t('Administer group'),
'description' => $this
->t('Manage group members and content in the group.'),
'default roles' => [
OgRoleInterface::ADMINISTRATOR,
],
'restrict access' => TRUE,
]),
new GroupPermission([
'name' => OgAccess::DELETE_GROUP_PERMISSION,
'title' => $this
->t('Delete group'),
'description' => $this
->t('Delete the group entity.'),
'default roles' => [
OgRoleInterface::ADMINISTRATOR,
],
]),
new GroupPermission([
'name' => OgAccess::UPDATE_GROUP_PERMISSION,
'title' => $this
->t('Edit group'),
'description' => $this
->t('Edit the group entity.'),
'default roles' => [
OgRoleInterface::ADMINISTRATOR,
],
]),
new GroupPermission([
'name' => 'subscribe',
'title' => $this
->t('Subscribe to group'),
'description' => $this
->t('Allow non-members to request membership to a group (approval required).'),
'roles' => [
OgRoleInterface::ANONYMOUS,
],
'default roles' => [
OgRoleInterface::ANONYMOUS,
],
]),
new GroupPermission([
'name' => 'subscribe without approval',
'title' => $this
->t('Subscribe to group (no approval required)'),
'description' => $this
->t('Allow non-members to join a group without an approval from group administrators.'),
'roles' => [
OgRoleInterface::ANONYMOUS,
],
'default roles' => [],
]),
new GroupPermission([
'name' => 'approve and deny subscription',
'title' => $this
->t('Approve and deny subscription'),
'description' => $this
->t("Users may allow or deny another user's subscription request."),
'default roles' => [
OgRoleInterface::ADMINISTRATOR,
],
]),
new GroupPermission([
'name' => 'add user',
'title' => $this
->t('Add user'),
'description' => $this
->t('Users may add other users to the group without approval.'),
'default roles' => [
OgRoleInterface::ADMINISTRATOR,
],
]),
new GroupPermission([
'name' => 'manage members',
'title' => $this
->t('Manage members'),
'description' => $this
->t('Users may remove group members and alter member status and roles.'),
'default roles' => [
OgRoleInterface::ADMINISTRATOR,
],
'restrict access' => TRUE,
]),
new GroupPermission([
'name' => 'administer permissions',
'title' => $this
->t('Administer permissions'),
'description' => $this
->t('Users may view, create, edit and delete permissions and roles within the group.'),
'default roles' => [
OgRoleInterface::ADMINISTRATOR,
],
'restrict access' => TRUE,
]),
]);
$group_content_permissions = $this
->getDefaultEntityOperationPermissions($event
->getGroupContentBundleIds());
$event
->setPermissions($group_content_permissions);
}
public function provideDefaultNodePermissions(PermissionEventInterface $event) {
$bundle_ids = $event
->getGroupContentBundleIds();
if (!array_key_exists('node', $bundle_ids)) {
return;
}
$permissions = [];
$bundle_info = $this->entityTypeBundleInfo
->getBundleInfo('node');
foreach ($bundle_ids['node'] as $bundle_id) {
$args = [
'%type_name' => $bundle_info[$bundle_id]['label'],
];
$permission_values = [
[
'name' => "create {$bundle_id} content",
'title' => $this
->t('%type_name: Create new content', $args),
'operation' => 'create',
],
[
'name' => "edit own {$bundle_id} content",
'title' => $this
->t('%type_name: Edit own content', $args),
'operation' => 'update',
'owner' => TRUE,
],
[
'name' => "edit any {$bundle_id} content",
'title' => $this
->t('%type_name: Edit any content', $args),
'operation' => 'update',
'owner' => FALSE,
],
[
'name' => "delete own {$bundle_id} content",
'title' => $this
->t('%type_name: Delete own content', $args),
'operation' => 'delete',
'owner' => TRUE,
],
[
'name' => "delete any {$bundle_id} content",
'title' => $this
->t('%type_name: Delete any content', $args),
'operation' => 'delete',
'owner' => FALSE,
],
];
foreach ($permission_values as $values) {
$values += [
'entity type' => 'node',
'bundle' => $bundle_id,
];
$permissions[] = new GroupContentOperationPermission($values);
}
}
$event
->setPermissions($permissions);
}
public function provideDefaultRoles(DefaultRoleEventInterface $event) {
$role = $this->entityTypeManager
->getStorage('og_role')
->create([
'name' => OgRoleInterface::ADMINISTRATOR,
'label' => 'Administrator',
'is_admin' => TRUE,
]);
$event
->addRole($role);
}
protected function getDefaultEntityOperationPermissions(array $group_content_bundle_ids) {
$permissions = [];
foreach ($group_content_bundle_ids as $group_content_entity_type_id => $bundle_ids) {
foreach ($bundle_ids as $bundle_id) {
$permissions += $this
->generateEntityOperationPermissionList($group_content_entity_type_id, $bundle_id);
}
}
return $permissions;
}
protected function generateEntityOperationPermissionList($group_content_entity_type_id, $group_content_bundle_id) {
$permissions = [];
$entity_info = $this->entityTypeManager
->getDefinition($group_content_entity_type_id);
$bundle_info = $this->entityTypeBundleInfo
->getBundleInfo($group_content_entity_type_id)[$group_content_bundle_id];
$args = [
'%bundle' => $bundle_info['label'],
'@entity' => $entity_info
->getPluralLabel(),
];
$operations = [
[
'name' => "create {$group_content_bundle_id} {$group_content_entity_type_id}",
'title' => $this
->t('Create %bundle @entity', $args),
'operation' => 'create',
],
[
'name' => "update own {$group_content_bundle_id} {$group_content_entity_type_id}",
'title' => $this
->t('Edit own %bundle @entity', $args),
'operation' => 'update',
'owner' => TRUE,
],
[
'name' => "update any {$group_content_bundle_id} {$group_content_entity_type_id}",
'title' => $this
->t('Edit any %bundle @entity', $args),
'operation' => 'update',
'owner' => FALSE,
],
[
'name' => "delete own {$group_content_bundle_id} {$group_content_entity_type_id}",
'title' => $this
->t('Delete own %bundle @entity', $args),
'operation' => 'delete',
'owner' => TRUE,
],
[
'name' => "delete any {$group_content_bundle_id} {$group_content_entity_type_id}",
'title' => $this
->t('Delete any %bundle @entity', $args),
'operation' => 'delete',
'owner' => FALSE,
],
];
foreach ($operations as $values) {
$permission = new GroupContentOperationPermission($values);
$permission
->setEntityType($group_content_entity_type_id)
->setBundle($group_content_bundle_id)
->setDefaultRoles([
OgRoleInterface::ADMINISTRATOR,
]);
$permissions[] = $permission;
}
return $permissions;
}
public function provideOgAdminRoutes(OgAdminRoutesEventInterface $event) {
$routes_info = $event
->getRoutesInfo();
$routes_info['members'] = [
'controller' => '\\Drupal\\og\\Controller\\OgAdminMembersController::membersList',
'title' => 'Members',
'description' => 'Manage members',
'path' => 'members',
'requirements' => [
'_og_user_access_group' => OgAccess::ADMINISTER_GROUP_PERMISSION,
'_module_dependencies' => 'views',
],
];
$event
->setRoutesInfo($routes_info);
}
public function checkGroupContentEntityOperationAccess(GroupContentEntityOperationAccessEventInterface $event) : void {
$group_content_entity = $event
->getGroupContent();
$group_entity = $event
->getGroup();
$user = $event
->getUser();
$operation = $event
->getOperation();
$is_owner = $group_content_entity instanceof EntityOwnerInterface && $group_content_entity
->getOwnerId() == $user
->id();
$group_entity_type_id = $group_entity
->getEntityTypeId();
$group_bundle_id = $group_entity
->bundle();
$group_content_bundle_ids = [
$group_content_entity
->getEntityTypeId() => [
$group_content_entity
->bundle(),
],
];
$permissions = $this->permissionManager
->getDefaultEntityOperationPermissions($group_entity_type_id, $group_bundle_id, $group_content_bundle_ids);
$ownerships = $is_owner ? [
FALSE,
TRUE,
] : [
FALSE,
];
$permissions = array_filter($permissions, function (GroupContentOperationPermission $permission) use ($operation, $ownerships) {
return $permission
->getOperation() === $operation && in_array($permission
->getOwner(), $ownerships);
});
if ($permissions) {
foreach ($permissions as $permission) {
$event
->mergeAccessResult($this->ogAccess
->userAccess($group_entity, $permission
->getName(), $user));
}
}
}
}