group-8.x-1.x-dev/tests/src/Unit/PermissionProviderTest.php
tests/src/Unit/PermissionProviderTest.php
<?php
namespace Drupal\Tests\group\Unit;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Tests\UnitTestCase;
use Drupal\group\Plugin\Group\Relation\GroupRelationType;
use Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface;
use Drupal\group\Plugin\Group\Relation\GroupRelationTypeManagerInterface;
use Drupal\group\Plugin\Group\RelationHandlerDefault\PermissionProvider;
use Drupal\group_test_plugin\Plugin\Group\RelationHandler\FullEntityPermissionProvider;
use Drupal\user\EntityOwnerInterface;
/**
* Tests the default group relation permission_provider handler.
*
* @coversDefaultClass \Drupal\group\Plugin\Group\RelationHandlerDefault\PermissionProvider
* @group group
*/
class PermissionProviderTest extends UnitTestCase {
/**
* Tests the admin permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
*
* @covers ::getAdminPermission
* @dataProvider adminPermissionProvider
*/
public function testGetAdminPermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getAdminPermission());
}
/**
* Data provider for testGetAdminPermission().
*
* @return array
* A list of testGetAdminPermission method arguments.
*/
public static function adminPermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
$case = $scenario;
$case['expected'] = $case['definition']->getAdminPermission();
$cases[] = $case;
}
return $cases;
}
/**
* Tests the relation view permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
* @param string $scope
* The $scope parameter for the tested method.
*
* @covers ::getPermission
* @dataProvider relationViewPermissionProvider
*/
public function testGetRelationViewPermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published, $scope) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getPermission('view', 'relationship', $scope));
}
/**
* Data provider for testGetRelationViewPermission().
*
* @return array
* A list of testGetRelationViewPermission method arguments.
*/
public static function relationViewPermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
foreach (['any', 'own'] as $scope) {
$case = $scenario;
$case['scope'] = $scope;
// View own relation is not present in version 1.x.
$case['expected'] = $scope === 'any'
? "view {$scenario['plugin_id']} relationship"
: FALSE;
$cases[] = $case;
}
}
return $cases;
}
/**
* Tests the relation update permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
* @param string $scope
* The $scope parameter for the tested method.
*
* @covers ::getPermission
* @dataProvider relationUpdatePermissionProvider
*/
public function testGetRelationUpdatePermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published, $scope) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getPermission('update', 'relationship', $scope));
}
/**
* Data provider for testGetRelationUpdatePermission().
*
* @return array
* A list of testGetRelationUpdatePermission method arguments.
*/
public static function relationUpdatePermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
foreach (['any', 'own'] as $scope) {
$case = $scenario;
$case['scope'] = $scope;
$case['expected'] = "update $scope {$scenario['plugin_id']} relationship";
$cases[] = $case;
}
}
return $cases;
}
/**
* Tests the relation delete permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
* @param string $scope
* The $scope parameter for the tested method.
*
* @covers ::getPermission
* @dataProvider relationDeletePermissionProvider
*/
public function testGetRelationDeletePermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published, $scope) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getPermission('delete', 'relationship', $scope));
}
/**
* Data provider for testGetRelationDeletePermission().
*
* @return array
* A list of testGetRelationDeletePermission method arguments.
*/
public static function relationDeletePermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
foreach (['any', 'own'] as $scope) {
$case = $scenario;
$case['scope'] = $scope;
$case['expected'] = "delete $scope {$scenario['plugin_id']} relationship";
$cases[] = $case;
}
}
return $cases;
}
/**
* Tests the relation create permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
*
* @covers ::getPermission
* @dataProvider relationCreatePermissionProvider
*/
public function testGetRelationCreatePermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getPermission('create', 'relationship'));
}
/**
* Data provider for testGetRelationCreatePermission().
*
* @return array
* A list of testGetRelationCreatePermission method arguments.
*/
public static function relationCreatePermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
$case = $scenario;
$case['expected'] = "create {$scenario['plugin_id']} relationship";
$cases[] = $case;
}
return $cases;
}
/**
* Tests the entity view permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
* @param string $scope
* The $scope parameter for the tested method.
*
* @covers ::getPermission
* @dataProvider entityViewPermissionProvider
*/
public function testGetEntityViewPermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published, $scope) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getPermission('view', 'entity', $scope));
}
/**
* Data provider for testGetEntityViewPermission().
*
* @return array
* A list of testGetEntityViewPermission method arguments.
*/
public static function entityViewPermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
foreach (['any', 'own'] as $scope) {
$case = $scenario;
$case['scope'] = $scope;
$case['expected'] = FALSE;
if ($case['definition']->definesEntityAccess()) {
// View own entity is not present in version 1.x.
if ($scope === 'any') {
$case['expected'] = "view {$scenario['plugin_id']} entity";
}
}
$cases[] = $case;
}
}
return $cases;
}
/**
* Tests the entity view unpublished permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
* @param string $scope
* The $scope parameter for the tested method.
*
* @covers ::getPermission
* @dataProvider entityViewUnpublishedPermissionProvider
*/
public function testGetEntityViewUnpublishedPermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published, $scope) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getPermission('view unpublished', 'entity', $scope));
}
/**
* Data provider for testGetEntityViewUnpublishedPermission().
*
* @return array
* A list of testGetEntityViewUnpublishedPermission method arguments.
*/
public static function entityViewUnpublishedPermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
foreach (['any', 'own'] as $scope) {
$case = $scenario;
$case['scope'] = $scope;
$case['expected'] = FALSE;
if ($case['definition']->definesEntityAccess() && $case['implements_published']) {
if ($case['implements_owner'] || $scope === 'any') {
$case['expected'] = "view $scope unpublished {$scenario['plugin_id']} entity";
}
}
$cases[] = $case;
}
}
return $cases;
}
/**
* Tests the entity update permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
* @param string $scope
* The $scope parameter for the tested method.
*
* @covers ::getPermission
* @dataProvider entityUpdatePermissionProvider
*/
public function testGetEntityUpdatePermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published, $scope) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getPermission('update', 'entity', $scope));
}
/**
* Data provider for testGetEntityUpdatePermission().
*
* @return array
* A list of testGetEntityUpdatePermission method arguments.
*/
public static function entityUpdatePermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
foreach (['any', 'own'] as $scope) {
$case = $scenario;
$case['scope'] = $scope;
$case['expected'] = FALSE;
if ($case['definition']->definesEntityAccess()) {
if ($case['implements_owner'] || $scope === 'any') {
$case['expected'] = "update $scope {$scenario['plugin_id']} entity";
}
}
$cases[] = $case;
}
}
return $cases;
}
/**
* Tests the entity delete permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
* @param string $scope
* The $scope parameter for the tested method.
*
* @covers ::getPermission
* @dataProvider entityDeletePermissionProvider
*/
public function testGetEntityDeletePermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published, $scope) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getPermission('delete', 'entity', $scope));
}
/**
* Data provider for testGetEntityDeletePermission().
*
* @return array
* A list of testGetEntityDeletePermission method arguments.
*/
public static function entityDeletePermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
foreach (['any', 'own'] as $scope) {
$case = $scenario;
$case['scope'] = $scope;
$case['expected'] = FALSE;
if ($case['definition']->definesEntityAccess()) {
if ($case['implements_owner'] || $scope === 'any') {
$case['expected'] = "delete $scope {$scenario['plugin_id']} entity";
}
}
$cases[] = $case;
}
}
return $cases;
}
/**
* Tests the entity create permission name.
*
* @param mixed $expected
* The expected return value.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
*
* @covers ::getPermission
* @dataProvider entityCreatePermissionProvider
*/
public function testGetEntityCreatePermission($expected, $plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published);
$this->assertEquals($expected, $permission_provider->getPermission('create', 'entity'));
}
/**
* Data provider for testGetEntityCreatePermission().
*
* @return array
* A list of testGetEntityCreatePermission method arguments.
*/
public static function entityCreatePermissionProvider() {
$cases = [];
foreach (self::getPermissionProviderScenarios() as $scenario) {
$case = $scenario;
$case['expected'] = FALSE;
if ($case['definition']->definesEntityAccess()) {
$case['expected'] = "create {$scenario['plugin_id']} entity";
}
$cases[] = $case;
}
return $cases;
}
/**
* Tests the permission builder.
*
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationTypeInterface $definition
* The plugin definition.
* @param bool $implements_owner
* Whether the plugin's entity type deals with ownership.
* @param bool $implements_published
* Whether the plugin's entity type deals with publishing of entities.
*
* @covers ::buildPermissions
* @dataProvider buildPermissionsProvider
*/
public function testBuildPermissions($plugin_id, GroupRelationTypeInterface $definition, $implements_owner, $implements_published) {
$permission_provider = $this->createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published, TRUE);
$permissions = $permission_provider->buildPermissions();
// Test the admin permission being restricted.
if (!empty($definition->getAdminPermission())) {
$admin_permission = $permission_provider->getAdminPermission();
$this->assertArrayHasKey($admin_permission, $permissions);
$this->assertArrayHasKey('restrict access', $permissions[$admin_permission]);
$this->assertTrue($permissions[$admin_permission]['restrict access']);
}
// We do not test all permissions here as they are thoroughly covered in
// their dedicated getter test. Simply test that the labels of common
// permissions are prefixed properly.
if ($permission = $permission_provider->getPermission('update', 'relationship')) {
$this->assertArrayHasKey($permission, $permissions);
$this->assertStringStartsWith('Relationship: ', $permissions[$permission]['title']);
}
if ($permission = $permission_provider->getPermission('update', 'entity')) {
$this->assertArrayHasKey($permission, $permissions);
$this->assertStringStartsWith('Entity: ', $permissions[$permission]['title']);
}
// Test that we call the full chain for permission names.
if ($implements_owner && $definition->definesEntityAccess()) {
$this->assertFalse($permission_provider->getPermission('view', 'entity', 'own'), 'The handler does not support view own entity');
$this->assertArrayHasKey("view own $plugin_id entity", $permissions, 'The full chain does support view own entity and therefore the permission is built');
}
}
/**
* Data provider for testBuildPermissions().
*
* @return array
* A list of testBuildPermissions method arguments.
*/
public static function buildPermissionsProvider() {
$cases = self::getPermissionProviderScenarios();
foreach ($cases as &$case) {
unset($case['expected']);
}
return $cases;
}
/**
* All possible scenarios for a permission provider.
*
* @return array
* A set of test cases to be used in data providers.
*/
protected static function getPermissionProviderScenarios() {
$scenarios = [];
foreach ([TRUE, FALSE] as $implements_owner) {
$keys[0] = $implements_owner ? 'owner' : 'no_owner';
foreach ([TRUE, FALSE] as $implements_published) {
$keys[1] = $implements_published ? 'pub' : 'no_pub';
foreach ([TRUE, FALSE] as $entity_access) {
$keys[2] = $entity_access ? 'access' : 'no_access';
foreach (['administer foo', FALSE] as $admin_permission) {
$keys[3] = $admin_permission ? 'admin' : 'no_admin';
$scenarios[implode('-', $keys)] = [
'expected' => NULL,
// We use a derivative ID to prove these work.
'plugin_id' => 'foo:baz',
'definition' => new GroupRelationType([
'id' => 'foo',
'label' => 'Foo',
'entity_type_id' => 'bar',
'entity_access' => $entity_access,
'admin_permission' => $admin_permission,
]),
'implements_owner' => $implements_owner,
'implements_published' => $implements_published,
];
}
}
}
}
return $scenarios;
}
/**
* Instantiates a default permission provider handler.
*
* @return \Drupal\group\Plugin\Group\RelationHandlerDefault\PermissionProvider
* The default permission provider handler.
*/
protected function createPermissionProvider($plugin_id, $definition, $implements_owner, $implements_published, $set_up_chain = FALSE) {
$this->assertNotEmpty($definition->getEntityTypeId());
$entity_type = $this->prophesize(EntityTypeInterface::class);
$entity_type->entityClassImplements(EntityOwnerInterface::class)->willReturn($implements_owner);
$entity_type->entityClassImplements(EntityPublishedInterface::class)->willReturn($implements_published);
$entity_type->getSingularLabel()->willReturn('Bar');
$entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
$entity_type_manager->getDefinition($definition->getEntityTypeId())->willReturn($entity_type->reveal());
$relation_type_manager = $this->prophesize(GroupRelationTypeManagerInterface::class);
$permission_provider = new PermissionProvider($entity_type_manager->reveal(), $relation_type_manager->reveal());
$permission_provider->init($plugin_id, $definition);
$chained = $permission_provider;
if ($set_up_chain) {
$chained = new FullEntityPermissionProvider($permission_provider, $entity_type_manager->reveal());
$chained->init($plugin_id, $definition);
}
$relation_type_manager->getPermissionProvider($plugin_id)->willReturn($chained);
return $permission_provider;
}
}
