diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php index 3f142df..ae955e0 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php @@ -66,6 +66,7 @@ public function __construct($definition) { $this->entity_keys['langcode'] = 'langcode'; $this->handlers += [ 'storage' => 'Drupal\Core\Config\Entity\ConfigEntityStorage', + 'permission_provider' => 'Drupal\Core\Entity\DefaultEntityPermissionProvider', ]; $this->lookup_keys[] = 'uuid'; } diff --git a/core/lib/Drupal/Core/Entity/DefaultEntityPermissionProvider.php b/core/lib/Drupal/Core/Entity/DefaultEntityPermissionProvider.php new file mode 100644 index 0000000..56318f2 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/DefaultEntityPermissionProvider.php @@ -0,0 +1,123 @@ +entityType = $entity_type; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { + return new static( + $entity_type + ); + } + + /** + * {@inheritdoc} + */ + public function buildPermissions() { + $permissions = []; + + if ($this->getAdminPermission()) { + $permissions = [ + $this->getAdminPermission() => [ + 'title' => $this->t('Administer @type', ['@type' => $this->entityType->getPluralLabel()]), + 'description' => $this->t('Maintain all the @type available.'), + 'restrict access' => TRUE, + ], + ]; + } + + return $permissions; + } + + /** + * {@inheritdoc} + */ + public function getAdminPermission() { + return $this->entityType->getAdminPermission(); + } + + /** + * {@inheritdoc} + */ + public function getCollectionPermission() { + } + + /** + * {@inheritdoc} + */ + public function getViewAnyPublishedPermission($bundle = NULL) { + } + + /** + * {@inheritdoc} + */ + public function getViewOwnPublishedPermission($bundle = NULL) { + } + + /** + * {@inheritdoc} + */ + public function getViewOwnUnpublishedPermission() { + } + + /** + * {@inheritdoc} + */ + public function getUpdateAnyPermission($bundle = NULL) { + } + + /** + * {@inheritdoc} + */ + public function getUpdateOwnPermission($bundle = NULL) { + } + + /** + * {@inheritdoc} + */ + public function getDeleteAnyPermission($bundle = NULL) { + } + + /** + * {@inheritdoc} + */ + public function getDeleteOwnPermission($bundle = NULL) { + } + + /** + * {@inheritdoc} + */ + public function getCreatePermission($bundle = NULL) { + } + +} diff --git a/core/lib/Drupal/Core/Entity/EditorialEntityPermissionProvider.php b/core/lib/Drupal/Core/Entity/EditorialEntityPermissionProvider.php new file mode 100644 index 0000000..e8c4c94 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EditorialEntityPermissionProvider.php @@ -0,0 +1,540 @@ + NULL, + 'collection' => NULL, + 'view any published' => NULL, + 'view own published' => NULL, + 'view own unpublished' => NULL, + 'edit any' => NULL, + 'edit own' => NULL, + 'delete any' => NULL, + 'delete own' => NULL, + 'create' => NULL, + ]; + + /** + * @var array + */ + protected $perBundlePermissionMap = [ + 'view any published' => NULL, + 'view own published' => NULL, + 'view own unpublished' => NULL, + 'edit any' => NULL, + 'edit own' => NULL, + 'delete any' => NULL, + 'delete own' => NULL, + 'create' => NULL, + ]; + + /** + * Constructs a new EditorialEntityPermissionProvider object. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type definition. + * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info + * The entity type bundle info. + */ + public function __construct(EntityTypeInterface $entity_type, EntityTypeBundleInfoInterface $entity_type_bundle_info) { + parent::__construct($entity_type); + $this->entityTypeBundleInfo = $entity_type_bundle_info; + + if (!isset($this->bundleGranularity)) { + if ($entity_type_permission_granularity = $this->entityType->getPermissionGranularity()) { + $this->bundleGranularity = $entity_type_permission_granularity === 'bundle' ? TRUE : FALSE; + } + else { + $this->bundleGranularity = $this->entityType->getBundleEntityType() ? TRUE : FALSE; + } + } + + if (!isset($this->ownerGranularity)) { + $this->ownerGranularity = $entity_type->entityClassImplements(EntityOwnerInterface::class); + } + + $this->buildPermissionMap(); + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { + return new static( + $entity_type, + $container->get('entity_type.bundle.info') + ); + } + + /** + * {@inheritdoc} + */ + public function buildPermissions() { + $permissions = []; + foreach (array_filter($this->permissionMap) as $key => $permission_name) { + $permissions[$permission_name] = $this->getPermissionInfo($key); + } + + if ($this->bundleGranularity) { + foreach (array_filter($this->perBundlePermissionMap) as $key => $permission_name) { + foreach ($this->entityTypeBundleInfo->getBundleInfo($this->entityType->id()) as $bundle_name => $bundle_info) { + $permission_name = $this->getPermissionNameForBundle($permission_name, $bundle_name); + $permissions[$permission_name] = $this->getPermissionInfoForBundle($key, $bundle_info); + } + } + } + + return $this->processPermissions($permissions); + } + + /** + * Generates the permission names for each supported permission key. + */ + protected function buildPermissionMap() { + $entity_type_id = $this->entityType->id(); + + $this->permissionMap['admin'] = "administer {$entity_type_id}"; + + if ($this->entityType->hasLinkTemplate('collection')) { + $this->permissionMap['collection'] = "access {$entity_type_id} overview"; + } + + // Don't include the operation name for the widely used 'view any published' + // permissions. + $this->permissionMap['view any published'] = "view {$entity_type_id}"; + + // Allow entity types that are usually admin-facing only to declare a poorly + // cacheable 'view own published' permission. + if ($this->ownerGranularity && $this->viewOwnPublishedPermission) { + $this->permissionMap['view own published'] = "view own {$entity_type_id}"; + } + + if ($this->ownerGranularity && $this->entityType->entityClassImplements(EntityPublishedInterface::class)) { + $this->permissionMap['view own unpublished'] = "view own unpublished {$entity_type_id}"; + } + + if (!$this->bundleGranularity) { + $this->buildPerEntityTypePermissionMap(); + } + else { + $this->buildPerBundlePermissionMap(); + } + } + + /** + * Generates the permission map for the 'entity type' granularity. + */ + protected function buildPerEntityTypePermissionMap() { + $entity_type_id = $this->entityType->id(); + + $this->permissionMap['create'] = "create {$entity_type_id}"; + + $this->permissionMap['edit any'] = "edit any {$entity_type_id}"; + $this->permissionMap['delete any'] = "delete any {$entity_type_id}"; + + if ($this->ownerGranularity) { + $this->permissionMap['edit own'] = "edit own {$entity_type_id}"; + $this->permissionMap['delete own'] = "delete own {$entity_type_id}"; + } + } + + /** + * Generates the permission map for the 'bundle' granularity. + */ + protected function buildPerBundlePermissionMap() { + $entity_type_id = $this->entityType->id(); + + if ($this->viewBundleGranularity) { + $this->perBundlePermissionMap['view any published'] = "view __BUNDLE__ {$entity_type_id}"; + + if ($this->ownerGranularity) { + $this->perBundlePermissionMap['view own published'] = "view own __BUNDLE__ {$entity_type_id}"; + } + } + + $this->perBundlePermissionMap['create'] = "create __BUNDLE__ {$entity_type_id}"; + + $this->perBundlePermissionMap['edit any'] = "edit any __BUNDLE__ {$entity_type_id}"; + $this->perBundlePermissionMap['delete any'] = "delete any __BUNDLE__ {$entity_type_id}"; + + if ($this->ownerGranularity) { + $this->perBundlePermissionMap['edit own'] = "edit own __BUNDLE__ {$entity_type_id}"; + $this->perBundlePermissionMap['delete own'] = "delete own __BUNDLE__ {$entity_type_id}"; + } + } + + /** + * Returns the permission values (e.g. title, etc.) for a permission key. + * + * @param string $permission_key + * A permission key as defined in self::$permissionMap. + * + * @return array + * An array of permission values. + */ + protected function getPermissionInfo($permission_key) { + $singular_label = $this->entityType->getSingularLabel(); + $plural_label = $this->entityType->getPluralLabel(); + + $info = []; + switch ($permission_key) { + case 'admin': + $info = [ + 'title' => $this->t('Administer @type', ['@type' => $plural_label]), + 'restrict access' => TRUE, + ]; + break; + + case 'collection': + $info = [ + 'title' => $this->t('Access the @type overview page', ['@type' => $plural_label]), + ]; + break; + + case 'view any published': + $info = [ + 'title' => $this->t('View @type', ['@type' => $plural_label]), + ]; + break; + + case 'view own published': + $info = [ + 'title' => $this->t('View own @type', ['@type' => $plural_label]), + ]; + break; + + case 'view own unpublished': + $info = [ + 'title' => $this->t('View own unpublished @type', ['@type' => $plural_label]), + ]; + break; + + case 'create': + $info = [ + 'title' => $this->t('Create @type', ['@type' => $plural_label]), + ]; + break; + + case 'edit any': + $info = [ + 'title' => $this->t('Edit any @type', ['@type' => $singular_label]), + ]; + break; + + case 'edit own': + $info = [ + 'title' => $this->t('Edit own @type', ['@type' => $plural_label]), + ]; + break; + + case 'delete any': + $info = [ + 'title' => $this->t('Delete any @type', ['@type' => $singular_label]), + ]; + break; + + case 'delete own': + $info = [ + 'title' => $this->t('Delete own @type', ['@type' => $plural_label]), + ]; + break; + + default: + break; + } + + return $info; + } + + /** + * Returns the permission values (e.g. title) for a per-bundle permission key. + * + * @param string $permission_key + * A permission key as defined in self::$perBundlePermissionMap. + * @param array $bundle_info + * An array of bundle information, as defined by + * \Drupal\Core\Entity\EntityTypeBundleInfoInterface::getBundleInfo(). + * + * @return array + * An array of permission values. + */ + protected function getPermissionInfoForBundle($permission_key, array $bundle_info) { + $singular_label = $this->entityType->getSingularLabel(); + $plural_label = $this->entityType->getPluralLabel(); + + $info = []; + switch ($permission_key) { + case 'view any published': + $info = [ + 'title' => $this->t('%bundle_name: View any @type', [ + '%bundle_name' => $bundle_info['label'], + '@type' => $plural_label, + ]), + ]; + break; + + case 'view own published': + $info = [ + 'title' => $this->t('%bundle_name: View own @type', [ + '%bundle_name' => $bundle_info['label'], + '@type' => $plural_label, + ]), + ]; + break; + + case 'create': + $info = [ + 'title' => $this->t('%bundle_name: Create @type', [ + '%bundle_name' => $bundle_info['label'], + '@type' => $plural_label, + ]), + ]; + break; + + case 'edit any': + $info = [ + 'title' => $this->t('%bundle_name: Edit any @type', [ + '%bundle_name' => $bundle_info['label'], + '@type' => $singular_label, + ]), + ]; + break; + + case 'edit own': + $info = [ + 'title' => $this->t('%bundle_name: Edit own @type', [ + '%bundle_name' => $bundle_info['label'], + '@type' => $plural_label, + ]), + ]; + break; + + case 'delete any': + $info = [ + 'title' => $this->t('%bundle_name: Delete any @type', [ + '%bundle_name' => $bundle_info['label'], + '@type' => $singular_label, + ]), + ]; + break; + + case 'delete own': + $info = [ + 'title' => $this->t('%bundle_name: Delete own @type', [ + '%bundle_name' => $bundle_info['label'], + '@type' => $plural_label, + ]), + ]; + break; + + default: + break; + } + + return $info; + } + + /** + * {@inheritdoc} + */ + public function getAdminPermission() { + return $this->permissionMap['admin']; + } + + /** + * {@inheritdoc} + */ + public function getCollectionPermission() { + return $this->permissionMap['collection']; + } + + /** + * {@inheritdoc} + */ + public function getViewAnyPublishedPermission($bundle = NULL) { + if ($this->bundleGranularity && $this->viewBundleGranularity) { + return $this->getPermissionNameForBundle('view any published', $bundle); + } + + return $this->permissionMap['view any published']; + } + + /** + * {@inheritdoc} + */ + public function getViewOwnPublishedPermission($bundle = NULL) { + if ($this->bundleGranularity && $this->viewBundleGranularity && $this->ownerGranularity) { + return $this->getPermissionNameForBundle('view own published', $bundle); + } + + return $this->permissionMap['view own published']; + } + + /** + * {@inheritdoc} + */ + public function getViewOwnUnpublishedPermission() { + return $this->permissionMap['view own unpublished']; + } + + /** + * {@inheritdoc} + */ + public function getUpdateAnyPermission($bundle = NULL) { + if ($this->bundleGranularity) { + return $this->getPermissionNameForBundle('edit any', $bundle); + } + + return $this->permissionMap['edit any']; + } + + /** + * {@inheritdoc} + */ + public function getUpdateOwnPermission($bundle = NULL) { + if ($this->bundleGranularity && $this->ownerGranularity) { + return $this->getPermissionNameForBundle('edit own', $bundle); + } + + return $this->permissionMap['edit own']; + } + + /** + * {@inheritdoc} + */ + public function getDeleteAnyPermission($bundle = NULL) { + if ($this->bundleGranularity) { + return $this->getPermissionNameForBundle('delete any', $bundle); + } + + return $this->permissionMap['delete any']; + + } + + /** + * {@inheritdoc} + */ + public function getDeleteOwnPermission($bundle = NULL) { + if ($this->bundleGranularity && $this->ownerGranularity) { + return $this->getPermissionNameForBundle('delete own', $bundle); + } + + return $this->permissionMap['delete own']; + } + + /** + * {@inheritdoc} + */ + public function getCreatePermission($bundle = NULL) { + if ($this->bundleGranularity) { + return $this->getPermissionNameForBundle($this->perBundlePermissionMap['create'], $bundle); + } + + return $this->permissionMap['create']; + } + + /** + * Returns the name of a bundle-specific permission. + * + * @param string $permission_name + * The name of the permission. + * @param string $bundle_name + * The name of the bundle. + * + * @return string + */ + protected function getPermissionNameForBundle($permission_name, $bundle_name) { + assert($bundle_name !== NULL); + return str_replace('__BUNDLE__', $bundle_name, $permission_name); + } + + /** + * Adds the provider and converts the titles to strings to allow sorting. + * + * @param array $permissions + * The array of permissions + * + * @return array + * An array of processed permissions. + */ + protected function processPermissions(array $permissions) { + foreach ($permissions as $name => $permission) { + // Permissions are grouped by provider on admin/people/permissions. + $permissions[$name]['provider'] = $this->entityType->getProvider(); + // TranslatableMarkup objects don't sort properly. + $permissions[$name]['title'] = (string) $permission['title']; + } + return $permissions; + } + +} diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index bc03175..a442196 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -147,6 +147,19 @@ public function getAccessControlHandler($entity_type) { /** * {@inheritdoc} * + * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0. + * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getPermissionProvider() + * instead. + * + * @see https://www.drupal.org/node/2549139 + */ + public function getPermissionProvider($entity_type) { + return $this->container->get('entity_type.manager')->getPermissionProvider($entity_type); + } + + /** + * {@inheritdoc} + * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. * Use \Drupal\Core\Entity\EntityTypeManagerInterface::getHandler() instead. * diff --git a/core/lib/Drupal/Core/Entity/EntityPermissionProvider.php b/core/lib/Drupal/Core/Entity/EntityPermissionProvider.php deleted file mode 100644 index 0d0c4e6..0000000 --- a/core/lib/Drupal/Core/Entity/EntityPermissionProvider.php +++ /dev/null @@ -1,91 +0,0 @@ -id(); - $plural_label = $entity_type->getPluralLabel(); - - $permissions["view {$entity_type_id}"] = [ - 'title' => $this->t('View @type', [ - '@type' => $plural_label, - ]), - ]; - - return $permissions; - } - - /** - * Builds permissions for the bundle granularity. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * - * @return array - * The permissions. - */ - protected function buildBundlePermissions(EntityTypeInterface $entity_type) { - $permissions = parent::buildBundlePermissions($entity_type); - $entity_type_id = $entity_type->id(); - $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id); - $plural_label = $entity_type->getPluralLabel(); - - $permissions["view {$entity_type_id}"] = [ - 'title' => $this->t('View @type', [ - '@type' => $plural_label, - ]), - ]; - foreach ($bundles as $bundle_name => $bundle_info) { - $permissions["view {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: View @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $plural_label, - ]), - ]; - } - - return $permissions; - } - -} diff --git a/core/lib/Drupal/Core/Entity/EntityPermissionProviderBase.php b/core/lib/Drupal/Core/Entity/EntityPermissionProviderBase.php deleted file mode 100644 index 6aab5fb9..0000000 --- a/core/lib/Drupal/Core/Entity/EntityPermissionProviderBase.php +++ /dev/null @@ -1,233 +0,0 @@ -entityTypeBundleInfo = $entity_type_bundle_info; - } - - /** - * {@inheritdoc} - */ - public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { - return new static( - $container->get('entity_type.bundle.info') - ); - } - - /** - * {@inheritdoc} - */ - public function buildPermissions(EntityTypeInterface $entity_type) { - $entity_type_id = $entity_type->id(); - $has_owner = $entity_type->entityClassImplements(EntityOwnerInterface::class); - $plural_label = $entity_type->getPluralLabel(); - - $permissions = []; - $permissions["administer {$entity_type_id}"] = [ - 'title' => $this->t('Administer @type', ['@type' => $plural_label]), - 'restrict access' => TRUE, - ]; - if ($entity_type->hasLinkTemplate('collection')) { - $permissions["access {$entity_type_id} overview"] = [ - 'title' => $this->t('Access the @type overview page', ['@type' => $plural_label]), - ]; - } - if ($has_owner && $entity_type->entityClassImplements(EntityPublishedInterface::class)) { - $permissions["view own unpublished {$entity_type_id}"] = [ - 'title' => $this->t('View own unpublished @type', [ - '@type' => $plural_label, - ]), - ]; - } - - // Generate the other permissions based on granularity. - $entity_type_permission_granularity = $entity_type->getPermissionGranularity(); - if ($entity_type_permission_granularity === 'entity_type') { - $permissions += $this->buildEntityTypePermissions($entity_type); - } - elseif ($entity_type_permission_granularity == 'bundle') { - $permissions += $this->buildBundlePermissions($entity_type); - } - else { - throw new EntityMalformedException('The entity type does not have an valid permission_granularity.'); - } - - return $this->processPermissions($permissions, $entity_type); - } - - /** - * Adds the provider and converts the titles to strings to allow sorting. - * - * @param array $permissions - * The array of permissions - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * - * @return array - * An array of processed permissions. - */ - protected function processPermissions(array $permissions, EntityTypeInterface $entity_type) { - foreach ($permissions as $name => $permission) { - // Permissions are grouped by provider on admin/people/permissions. - $permissions[$name]['provider'] = $entity_type->getProvider(); - // TranslatableMarkup objects don't sort properly. - $permissions[$name]['title'] = (string) $permission['title']; - } - return $permissions; - } - - /** - * Builds permissions for the entity_type granularity. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * - * @return array - * The permissions. - */ - protected function buildEntityTypePermissions(EntityTypeInterface $entity_type) { - $entity_type_id = $entity_type->id(); - $has_owner = $entity_type->entityClassImplements(EntityOwnerInterface::class); - $singular_label = $entity_type->getSingularLabel(); - $plural_label = $entity_type->getPluralLabel(); - - $permissions = []; - $permissions["create {$entity_type_id}"] = [ - 'title' => $this->t('Create @type', [ - '@type' => $plural_label, - ]), - ]; - if ($has_owner) { - $permissions["update any {$entity_type_id}"] = [ - 'title' => $this->t('Update any @type', [ - '@type' => $singular_label, - ]), - ]; - $permissions["update own {$entity_type_id}"] = [ - 'title' => $this->t('Update own @type', [ - '@type' => $plural_label, - ]), - ]; - $permissions["delete any {$entity_type_id}"] = [ - 'title' => $this->t('Delete any @type', [ - '@type' => $singular_label, - ]), - ]; - $permissions["delete own {$entity_type_id}"] = [ - 'title' => $this->t('Delete own @type', [ - '@type' => $plural_label, - ]), - ]; - } - else { - $permissions["update {$entity_type_id}"] = [ - 'title' => $this->t('Update @type', [ - '@type' => $plural_label, - ]), - ]; - $permissions["delete {$entity_type_id}"] = [ - 'title' => $this->t('Delete @type', [ - '@type' => $plural_label, - ]), - ]; - } - - return $permissions; - } - - /** - * Builds permissions for the bundle granularity. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * - * @return array - * The permissions. - */ - protected function buildBundlePermissions(EntityTypeInterface $entity_type) { - $entity_type_id = $entity_type->id(); - $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id); - $has_owner = $entity_type->entityClassImplements(EntityOwnerInterface::class); - $singular_label = $entity_type->getSingularLabel(); - $plural_label = $entity_type->getPluralLabel(); - - $permissions = []; - foreach ($bundles as $bundle_name => $bundle_info) { - $permissions["create {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: Create @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $plural_label, - ]), - ]; - - if ($has_owner) { - $permissions["update any {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: Update any @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $singular_label, - ]), - ]; - $permissions["update own {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: Update own @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $plural_label, - ]), - ]; - $permissions["delete any {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: Delete any @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $singular_label, - ]), - ]; - $permissions["delete own {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: Delete own @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $plural_label, - ]), - ]; - } - else { - $permissions["update {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: Update @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $plural_label, - ]), - ]; - $permissions["delete {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: Delete @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $plural_label, - ]), - ]; - } - } - - return $permissions; - } - -} diff --git a/core/lib/Drupal/Core/Entity/EntityPermissionProviderInterface.php b/core/lib/Drupal/Core/Entity/EntityPermissionProviderInterface.php index 212a852..8f55429 100644 --- a/core/lib/Drupal/Core/Entity/EntityPermissionProviderInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityPermissionProviderInterface.php @@ -3,23 +3,114 @@ namespace Drupal\Core\Entity; /** - * Allows entity types to provide permissions. + * Provides an interface for entity permission providers. */ interface EntityPermissionProviderInterface { /** - * Builds permissions for the given entity type. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. + * Builds permissions for an entity type. * * @return array[] - * The permissions. - * Each permission is an array with the following keys: - * - title: The title of the permission. - * - description: The description of the permission. - * - provider: The provider of the permission. + * An associative array of permission values, keyed by permission name. + * + * @see \Drupal\user\PermissionHandlerInterface::getPermissions() + */ + public function buildPermissions(); + + /** + * Gets the name of the admin permission. + * + * @return string|null + */ + public function getAdminPermission(); + + /** + * Gets the name of the collection permission. + * + * This permission is mostly used for providing access to the 'overview' page + * of an entity type. For other kind of listings, for example one that is + * provided by a HTTP REST API, the 'view any published' permission should be + * used instead. + * + * @return string|null + */ + public function getCollectionPermission(); + + /** + * Gets the name of the 'view any published' permission. + * + * @param string $bundle + * (optional) A bundle name. + * + * @return string|null + */ + public function getViewAnyPublishedPermission($bundle = NULL); + + /** + * Gets the name of the 'view own published' permission. + * + * @param string $bundle + * (optional) A bundle name. + * + * @return string|null + */ + public function getViewOwnPublishedPermission($bundle = NULL); + + /** + * Gets the name of the 'view own unpublished' permission. + * + * @return string|null + */ + public function getViewOwnUnpublishedPermission(); + + /** + * Gets the name of the 'edit any' permission. + * + * @param string $bundle + * (optional) A bundle name. + * + * @return string|null + */ + public function getUpdateAnyPermission($bundle = NULL); + + /** + * Gets the name of the 'edit own' permission. + * + * @param string $bundle + * (optional) A bundle name. + * + * @return string|null + */ + public function getUpdateOwnPermission($bundle = NULL); + + /** + * Gets the name of the 'delete any' permission. + * + * @param string $bundle + * (optional) A bundle name. + * + * @return string|null + */ + public function getDeleteAnyPermission($bundle = NULL); + + /** + * Gets the name of the 'delete own' permission. + * + * @param string $bundle + * (optional) A bundle name. + * + * @return string|null + */ + public function getDeleteOwnPermission($bundle = NULL); + + /** + * Gets the name of the 'create' permission. + * + * @param string $bundle + * (optional) A bundle name. + * + * @return string|null */ - public function buildPermissions(EntityTypeInterface $entity_type); + public function getCreatePermission($bundle = NULL); } diff --git a/core/lib/Drupal/Core/Entity/EntityPermissions.php b/core/lib/Drupal/Core/Entity/EntityPermissions.php deleted file mode 100644 index b24e30c..0000000 --- a/core/lib/Drupal/Core/Entity/EntityPermissions.php +++ /dev/null @@ -1,62 +0,0 @@ -entityTypeManager = $entity_type_manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('entity_type.manager') - ); - } - - /** - * Builds a list of permissions for the participating entity types. - * - * @return array - * The permissions. - */ - public function buildPermissions() { - $permissions = []; - /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */ - foreach ($this->entityTypeManager->getDefinitions() as $entity_type) { - if ($entity_type->hasHandlerClass('permission_provider')) { - $permission_provider_class = $entity_type->getHandlerClass('permission_provider'); - $permission_provider = $this->entityTypeManager->createHandlerInstance($permission_provider_class, $entity_type); - $permissions += $permission_provider->buildPermissions($entity_type); - } - } - - return $permissions; - } - -} diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php index c6f320f..bb7a5a0 100644 --- a/core/lib/Drupal/Core/Entity/EntityType.php +++ b/core/lib/Drupal/Core/Entity/EntityType.php @@ -611,6 +611,28 @@ public function setAccessClass($class) { /** * {@inheritdoc} */ + public function hasPermissionProviderClass() { + return $this->hasHandlerClass('permission_provider'); + } + + /** + * {@inheritdoc} + */ + public function getPermissionProviderClass() { + return $this->getHandlerClass('permission_provider'); + } + + /** + * {@inheritdoc} + */ + public function setPermissionProviderClass($class) { + $this->handlers['permission_provider'] = $class; + return $this; + } + + /** + * {@inheritdoc} + */ public function getAdminPermission() { return $this->admin_permission ?: FALSE; } diff --git a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php index b2c1f5d..6de816c 100644 --- a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php @@ -345,6 +345,33 @@ public function getAccessControlClass(); public function setAccessClass($class); /** + * Indicates if this entity type has a permission provider class. + * + * @return bool + * TRUE if there is a permission provider class for this entity type, FALSE + * otherwise. + */ + public function hasPermissionProviderClass(); + + /** + * Gets the permission provider class. + * + * @return string + * The class for this entity type's permission provider. + */ + public function getPermissionProviderClass(); + + /** + * Sets the permission provider handler class. + * + * @param string $class + * The class for this entity type's permission provider handler. + * + * @return $this + */ + public function setPermissionProviderClass($class); + + /** * Indicates if the entity type class implements the given interface. * * @param string $interface diff --git a/core/lib/Drupal/Core/Entity/EntityTypeManager.php b/core/lib/Drupal/Core/Entity/EntityTypeManager.php index 9d7fdc5..4477be5 100644 --- a/core/lib/Drupal/Core/Entity/EntityTypeManager.php +++ b/core/lib/Drupal/Core/Entity/EntityTypeManager.php @@ -229,6 +229,13 @@ public function getAccessControlHandler($entity_type) { /** * {@inheritdoc} */ + public function getPermissionProvider($entity_type) { + return $this->getHandler($entity_type, 'permission_provider'); + } + + /** + * {@inheritdoc} + */ public function getHandler($entity_type, $handler_type) { if (!isset($this->handlers[$handler_type][$entity_type])) { $definition = $this->getDefinition($entity_type); diff --git a/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php index 0ccac97..e0fc63b 100644 --- a/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php @@ -83,6 +83,17 @@ public function getFormObject($entity_type, $operation); public function getRouteProviders($entity_type); /** + * Creates a new permission provider handler instance. + * + * @param string $entity_type + * The entity type for this permission provider handler. + * + * @return \Drupal\Core\Entity\EntityPermissionProviderInterface + * A permission provider handler instance. + */ + public function getPermissionProvider($entity_type); + + /** * Checks whether a certain entity type has a certain handler. * * @param string $entity_type diff --git a/core/lib/Drupal/Core/Entity/PermissionBasedEntityAccessControlHandler.php b/core/lib/Drupal/Core/Entity/PermissionBasedEntityAccessControlHandler.php deleted file mode 100644 index f33c069..0000000 --- a/core/lib/Drupal/Core/Entity/PermissionBasedEntityAccessControlHandler.php +++ /dev/null @@ -1,142 +0,0 @@ -hasHandlerClass('permission_provider') || !is_a($entity_type->getHandlerClass('permission_provider'), EntityPermissionProvider::class, TRUE)) { - throw new \Exception("This entity access control handler requires the entity permissions provider: {EntityPermissionProvider::class}"); - } - } - - /** - * {@inheritdoc} - */ - protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { - $account = $this->prepareUser($account); - /** @var \Drupal\Core\Access\AccessResult $result */ - $result = parent::checkAccess($entity, $operation, $account); - - if ($result->isNeutral()) { - if ($entity instanceof EntityOwnerInterface) { - $result = $this->checkEntityOwnerPermissions($entity, $operation, $account); - } - else { - $result = $this->checkEntityPermissions($entity, $operation, $account); - } - } - - // Ensure that access is evaluated again when the entity changes. - return $result->addCacheableDependency($entity); - } - - /** - * Checks the entity operation and bundle permissions. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity for which to check access. - * @param string $operation - * The entity operation. Usually one of 'view', 'view label', 'update' or - * 'delete'. - * @param \Drupal\Core\Session\AccountInterface $account - * The user for which to check access. - * - * @return \Drupal\Core\Access\AccessResultInterface - * The access result. - */ - protected function checkEntityPermissions(EntityInterface $entity, $operation, AccountInterface $account) { - $permissions = [ - "$operation {$entity->getEntityTypeId()}", - "$operation {$entity->bundle()} {$entity->getEntityTypeId()}", - ]; - - return AccessResult::allowedIfHasPermissions($account, $permissions, 'OR'); - } - - /** - * Checks the entity operation and bundle permissions, with owners. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity for which to check access. - * @param string $operation - * The entity operation. Usually one of 'view', 'view label', 'update' or - * 'delete'. - * @param \Drupal\Core\Session\AccountInterface $account - * The user for which to check access. - * - * @return \Drupal\Core\Access\AccessResultInterface - * The access result. - */ - protected function checkEntityOwnerPermissions(EntityInterface $entity, $operation, AccountInterface $account) { - if ($operation === 'view') { - if ($entity instanceof EntityPublishedInterface && !$entity->isPublished()) { - if ($account->id() == $entity->getOwnerId()) { - $permissions = [ - "view own unpublished {$entity->getEntityTypeId()}", - ]; - return AccessResult::allowedIfHasPermissions($account, $permissions) - ->cachePerUser(); - } - return AccessResult::neutral()->cachePerUser(); - } - else { - return AccessResult::allowedIfHasPermissions($account, [ - "view {$entity->getEntityTypeId()}", - "view {$entity->bundle()} {$entity->getEntityTypeId()}", - ], 'OR'); - } - } - else { - if ($account->id() == $entity->getOwnerId()) { - $result = AccessResult::allowedIfHasPermissions($account, [ - "$operation own {$entity->getEntityTypeId()}", - "$operation any {$entity->getEntityTypeId()}", - "$operation own {$entity->bundle()} {$entity->getEntityTypeId()}", - "$operation any {$entity->bundle()} {$entity->getEntityTypeId()}", - ], 'OR'); - } - else { - $result = AccessResult::allowedIfHasPermissions($account, [ - "$operation any {$entity->getEntityTypeId()}", - "$operation any {$entity->bundle()} {$entity->getEntityTypeId()}", - ], 'OR'); - } - return $result; - } - } - - /** - * {@inheritdoc} - */ - protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { - $result = parent::checkCreateAccess($account, $context, $entity_bundle); - if ($result->isNeutral()) { - $permissions = [ - 'administer ' . $this->entityTypeId, - 'create ' . $this->entityTypeId, - ]; - if ($entity_bundle) { - $permissions[] = 'create ' . $entity_bundle . ' ' . $this->entityTypeId; - } - - $result = AccessResult::allowedIfHasPermissions($account, $permissions, 'OR')->cachePerUser(); - } - - return $result; - } - -} diff --git a/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php index 5aeea9e..fa3c2be 100644 --- a/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php @@ -318,26 +318,28 @@ protected function getDeleteFormRoute(EntityTypeInterface $entity_type) { protected function getCollectionRoute(EntityTypeInterface $entity_type) { // If the entity type does not provide an admin permission, there is no way // to control access, so we cannot provide a route in a sensible way. - if ($entity_type->hasLinkTemplate('collection') && $entity_type->hasListBuilderClass() && ($admin_permission = $entity_type->getAdminPermission())) { - // Support access overview permission. - if ($entity_type->hasHandlerClass('permission_provider')) { - $overview_permission = "access {$entity_type->id()} overview"; - $admin_permission = "$admin_permission+$overview_permission"; - } - /** @var \Drupal\Core\StringTranslation\TranslatableMarkup $label */ - $label = $entity_type->getCollectionLabel(); + if ($entity_type->hasLinkTemplate('collection') && $entity_type->hasListBuilderClass() && $entity_type->hasPermissionProviderClass()) { + $permission_provider = $this->entityTypeManager->getPermissionProvider($entity_type); + $admin_permission = $permission_provider->getAdminPermission(); + $collection_permission = $permission_provider->getCollectionPermission(); - $route = new Route($entity_type->getLinkTemplate('collection')); - $route - ->addDefaults([ - '_entity_list' => $entity_type->id(), - '_title' => $label->getUntranslatedString(), - '_title_arguments' => $label->getArguments(), - '_title_context' => $label->getOption('context'), - ]) - ->setRequirement('_permission', $admin_permission); + if ($admin_permission || $collection_permission) { + $permission = implode('+', [$admin_permission, $collection_permission]); + /** @var \Drupal\Core\StringTranslation\TranslatableMarkup $label */ + $label = $entity_type->getCollectionLabel(); - return $route; + $route = new Route($entity_type->getLinkTemplate('collection')); + $route + ->addDefaults([ + '_entity_list' => $entity_type->id(), + '_title' => $label->getUntranslatedString(), + '_title_arguments' => $label->getArguments(), + '_title_context' => $label->getOption('context'), + ]) + ->setRequirement('_permission', $permission); + + return $route; + } } } diff --git a/core/lib/Drupal/Core/Entity/UncacheableEntityAccessControlHandler.php b/core/lib/Drupal/Core/Entity/UncacheableEntityAccessControlHandler.php deleted file mode 100644 index ca2c68e..0000000 --- a/core/lib/Drupal/Core/Entity/UncacheableEntityAccessControlHandler.php +++ /dev/null @@ -1,141 +0,0 @@ -hasHandlerClass('permission_provider') || !is_a($entity_type->getHandlerClass('permission_provider'), UncacheableEntityPermissionProvider::class, TRUE)) { - throw new \Exception("This entity access control handler requires the entity permissions provider: {EntityPermissionProvider::class}"); - } - } - - - /** - * {@inheritdoc} - */ - protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { - $account = $this->prepareUser($account); - /** @var \Drupal\Core\Access\AccessResult $result */ - $result = parent::checkAccess($entity, $operation, $account); - - if ($result->isNeutral()) { - if ($entity instanceof EntityOwnerInterface) { - $result = $this->checkEntityOwnerPermissions($entity, $operation, $account); - } - else { - $result = $this->checkEntityPermissions($entity, $operation, $account); - } - } - - // Ensure that access is evaluated again when the entity changes. - return $result->addCacheableDependency($entity); - } - - /** - * Checks the entity operation and bundle permissions. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity for which to check access. - * @param string $operation - * The entity operation. Usually one of 'view', 'view label', 'update' or - * 'delete'. - * @param \Drupal\Core\Session\AccountInterface $account - * The user for which to check access. - * - * @return \Drupal\Core\Access\AccessResultInterface - * The access result. - */ - protected function checkEntityPermissions(EntityInterface $entity, $operation, AccountInterface $account) { - return AccessResult::allowedIfHasPermissions($account, [ - "$operation {$entity->getEntityTypeId()}", - "$operation {$entity->bundle()} {$entity->getEntityTypeId()}", - ], 'OR'); - } - - /** - * Checks the entity operation and bundle permissions, with owners. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity for which to check access. - * @param string $operation - * The entity operation. Usually one of 'view', 'view label', 'update' or - * 'delete'. - * @param \Drupal\Core\Session\AccountInterface $account - * The user for which to check access. - * - * @return \Drupal\Core\Access\AccessResultInterface - * The access result. - */ - protected function checkEntityOwnerPermissions(EntityInterface $entity, $operation, AccountInterface $account) { - /** @var \Drupal\user\EntityOwnerInterface $entity */ - if ($operation === 'view' && $entity instanceof EntityPublishedInterface && !$entity->isPublished()) { - if ($account->id() != $entity->getOwnerId()) { - // There's no permission for viewing other user's unpublished entity. - return AccessResult::neutral()->cachePerUser(); - } - - $permissions = [ - "view own unpublished {$entity->getEntityTypeId()}", - ]; - $result = AccessResult::allowedIfHasPermissions($account, $permissions)->cachePerUser(); - } - else { - if ($account->id() == $entity->getOwnerId()) { - $permissions = [ - "$operation own {$entity->getEntityTypeId()}", - "$operation any {$entity->getEntityTypeId()}", - "$operation own {$entity->bundle()} {$entity->getEntityTypeId()}", - "$operation any {$entity->bundle()} {$entity->getEntityTypeId()}", - ]; - } - else { - $permissions = [ - "$operation any {$entity->getEntityTypeId()}", - "$operation any {$entity->bundle()} {$entity->getEntityTypeId()}", - ]; - } - - $result = AccessResult::allowedIfHasPermissions($account, $permissions, 'OR')->cachePerUser(); - } - - return $result; - } - - /** - * {@inheritdoc} - */ - protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { - $result = parent::checkCreateAccess($account, $context, $entity_bundle); - if ($result->isNeutral()) { - $permissions = [ - 'administer ' . $this->entityTypeId, - 'create ' . $this->entityTypeId, - ]; - if ($entity_bundle) { - $permissions[] = 'create ' . $entity_bundle . ' ' . $this->entityTypeId; - } - - $result = AccessResult::allowedIfHasPermissions($account, $permissions, 'OR'); - } - - return $result; - } - -} diff --git a/core/lib/Drupal/Core/Entity/UncacheableEntityPermissionProvider.php b/core/lib/Drupal/Core/Entity/UncacheableEntityPermissionProvider.php deleted file mode 100644 index 0b0c666..0000000 --- a/core/lib/Drupal/Core/Entity/UncacheableEntityPermissionProvider.php +++ /dev/null @@ -1,137 +0,0 @@ -id(); - $has_owner = $entity_type->entityClassImplements(EntityOwnerInterface::class); - $plural_label = $entity_type->getPluralLabel(); - - if ($has_owner) { - $permissions["view any {$entity_type_id}"] = [ - 'title' => $this->t('View any @type', [ - '@type' => $plural_label, - ]), - ]; - $permissions["view own {$entity_type_id}"] = [ - 'title' => $this->t('View own @type', [ - '@type' => $plural_label, - ]), - ]; - } - else { - $permissions["view any {$entity_type_id}"] = [ - 'title' => $this->t('View any @type', [ - '@type' => $plural_label, - ]), - ]; - } - - return $permissions; - } - - /** - * Builds permissions for the bundle granularity. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * - * @return array - * The permissions. - */ - protected function buildBundlePermissions(EntityTypeInterface $entity_type) { - $permissions = parent::buildBundlePermissions($entity_type); - $entity_type_id = $entity_type->id(); - $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id); - $has_owner = $entity_type->entityClassImplements(EntityOwnerInterface::class); - $plural_label = $entity_type->getPluralLabel(); - - $permissions["view any {$entity_type_id}"] = [ - 'title' => $this->t('View any @type', [ - '@type' => $plural_label, - ]), - ]; - if ($has_owner) { - $permissions["view own {$entity_type_id}"] = [ - 'title' => $this->t('View own @type', [ - '@type' => $plural_label, - ]), - ]; - } - - foreach ($bundles as $bundle_name => $bundle_info) { - if ($has_owner) { - $permissions["view any {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: View any @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $plural_label, - ]), - ]; - $permissions["view own {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: View own @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $plural_label, - ]), - ]; - } - else { - $permissions["view any {$bundle_name} {$entity_type_id}"] = [ - 'title' => $this->t('@bundle: View any @type', [ - '@bundle' => $bundle_info['label'], - '@type' => $plural_label, - ]), - ]; - } - } - - return $permissions; - } - -} diff --git a/core/modules/user/src/PermissionHandler.php b/core/modules/user/src/PermissionHandler.php index 66e066e..a3fe023 100644 --- a/core/modules/user/src/PermissionHandler.php +++ b/core/modules/user/src/PermissionHandler.php @@ -212,10 +212,9 @@ protected function buildEntityTypePermissions() { $permissions = []; /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */ foreach ($this->entityTypeManager->getDefinitions() as $entity_type) { - if ($entity_type->hasHandlerClass('permission_provider')) { - $permission_provider_class = $entity_type->getHandlerClass('permission_provider'); - $permission_provider = $this->entityTypeManager->createHandlerInstance($permission_provider_class, $entity_type); - $permissions += $permission_provider->buildPermissions($entity_type); + if ($entity_type->hasPermissionProviderClass()) { + $permission_provider = $this->entityTypeManager->getPermissionProvider($entity_type); + $permissions += $permission_provider->buildPermissions(); } } diff --git a/core/modules/user/tests/src/Unit/PermissionHandlerTest.php b/core/modules/user/tests/src/Unit/PermissionHandlerTest.php index d85c77d..85320b5 100644 --- a/core/modules/user/tests/src/Unit/PermissionHandlerTest.php +++ b/core/modules/user/tests/src/Unit/PermissionHandlerTest.php @@ -12,7 +12,6 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Extension\Extension; -use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\StringTranslation\PluralTranslatableMarkup; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\StringTranslation\TranslationInterface; @@ -108,10 +107,8 @@ public function testBuildPermissionsYaml() { vfsStreamWrapper::register(); $root = new vfsStreamDirectory('modules'); vfsStreamWrapper::setRoot($root); - $definitions = []; - $this->entityTypeManager->getDefinitions()->willReturn($definitions); - $this->moduleHandler = $this->getMock(ModuleHandlerInterface::class); + $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); $this->moduleHandler->expects($this->once()) ->method('getModuleDirectories') ->willReturn([ @@ -186,7 +183,7 @@ public function testBuildPermissionsSortPerModule() { $root = new vfsStreamDirectory('modules'); vfsStreamWrapper::setRoot($root); - $this->moduleHandler = $this->getMock(ModuleHandlerInterface::class); + $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); $this->moduleHandler->expects($this->once()) ->method('getModuleDirectories') ->willReturn([ @@ -225,13 +222,7 @@ public function testBuildPermissionsSortPerModule() { $permissionHandler = new TestPermissionHandler($this->entityTypeManager->reveal(), $this->moduleHandler, $this->stringTranslation, $this->controllerResolver); $actual_permissions = $permissionHandler->getPermissions(); - $expected = [ - 'access_module_a4', - 'access_module_a1', - 'access_module_a2', - 'access_module_a3', - ]; - $this->assertEquals($expected, + $this->assertEquals(['access_module_a4', 'access_module_a1', 'access_module_a2', 'access_module_a3'], array_keys($actual_permissions)); } @@ -247,7 +238,7 @@ public function testBuildPermissionsYamlCallback() { $root = new vfsStreamDirectory('modules'); vfsStreamWrapper::setRoot($root); - $this->moduleHandler = $this->getMock(ModuleHandlerInterface::class); + $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); $this->moduleHandler->expects($this->once()) ->method('getModuleDirectories') ->willReturn([ @@ -384,7 +375,7 @@ public function testPermissionsYamlStaticAndCallback() { * Checks that the permissions are like expected. * * @param array $actual_permissions - * The actual permissions. + * The actual permissions */ protected function assertPermissions(array $actual_permissions) { $this->assertCount(4, $actual_permissions); @@ -401,7 +392,7 @@ protected function assertPermissions(array $actual_permissions) { /** * Sets up the entity type manager to be tested. * - * @param \Drupal\Core\Entity\EntityTypeInterface[]|\Prophecy\Prophecy\ProphecyInterface[] $definitions + * @param \Drupal\Core\Entity\EntityTypeInterface[] $definitions * (optional) An array of entity type definitions. */ protected function setUpEntityTypeDefinitions($definitions = []) { @@ -437,11 +428,6 @@ protected function setUpEntityTypeDefinitions($definitions = []) { } -/** - * Class TestPermissionHandler. - * - * @package Drupal\Tests\user\Unit - */ class TestPermissionHandler extends PermissionHandler { /** @@ -451,30 +437,16 @@ class TestPermissionHandler extends PermissionHandler { */ protected $systemModuleData; - /** - * {@inheritdoc} - */ protected function systemRebuildModuleData() { return $this->systemModuleData; } - /** - * Setter for module rebuild data. - * - * @param array $extensions - * An array of extensions. - */ public function setSystemRebuildModuleData(array $extensions) { $this->systemModuleData = $extensions; } } -/** - * Class TestPermissionCallbacks. - * - * @package Drupal\Tests\user\Unit - */ class TestPermissionCallbacks { public function singleDescription() { @@ -483,12 +455,6 @@ public function singleDescription() { ]; } - /** - * Provides title description. - * - * @return array - * An array of description keyed by module name. - */ public function titleDescription() { return [ 'access module b' => [ @@ -498,12 +464,6 @@ public function titleDescription() { ]; } - /** - * Provides title description with restricted access. - * - * @return array - * An array of description keyed by module name. - */ public function titleDescriptionRestrictAccess() { return [ 'access_module_c' => [ @@ -514,12 +474,6 @@ public function titleDescriptionRestrictAccess() { ]; } - /** - * Provides title. - * - * @return array - * An array of description keyed by module name. - */ public function titleProvider() { return [ 'access module a via module b' => [ diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityPermissionProviderTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityPermissionProviderTest.php deleted file mode 100644 index 4a5e1b6..0000000 --- a/core/tests/Drupal/Tests/Core/Entity/EntityPermissionProviderTest.php +++ /dev/null @@ -1,236 +0,0 @@ -prophesize(EntityTypeBundleInfoInterface::class); - $entity_type_bundle_info->getBundleInfo('white_entity')->willReturn([ - 'first' => ['label' => 'First'], - 'second' => ['label' => 'Second'], - ]); - $entity_type_bundle_info->getBundleInfo('black_entity')->willReturn([ - 'third' => ['label' => 'Third'], - ]); - $entity_type_bundle_info->getBundleInfo('pink_entity')->willReturn([ - 'third' => ['label' => 'Third'], - ]); - $this->permissionProvider = new EntityPermissionProvider($entity_type_bundle_info->reveal()); - $this->permissionProvider->setStringTranslation($this->getStringTranslationStub()); - } - - /** - * @covers ::buildPermissions - * - * @dataProvider entityTypeProvider - */ - public function testBuildPermissions(EntityTypeInterface $entity_type, array $expected_permissions) { - $permissions = $this->permissionProvider->buildPermissions($entity_type); - $this->assertEquals(array_keys($expected_permissions), array_keys($permissions)); - foreach ($permissions as $name => $permission) { - $this->assertEquals('entity_module_test', $permission['provider']); - $this->assertEquals($expected_permissions[$name], $permission['title']); - } - } - - /** - * Data provider for testBuildPermissions(). - * - * @return array - * A list of testBuildPermissions method arguments. - */ - public function entityTypeProvider() { - $data = []; - // Content entity type. - $entity_type = $this->prophesizeEntityType( - 'green', - [ - EntityOwnerInterface::class => FALSE, - EntityPublishedInterface::class => FALSE, - ], - 'entity_type', - ['collection' => TRUE]); - $expected_permissions = [ - 'administer green_entity' => 'Administer green entities', - 'access green_entity overview' => 'Access the green entities overview page', - 'create green_entity' => 'Create green entities', - 'update green_entity' => 'Update green entities', - 'delete green_entity' => 'Delete green entities', - 'view green_entity' => 'View green entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // Content entity type with owner. - $entity_type = $this->prophesizeEntityType( - 'blue', - [ - EntityOwnerInterface::class => TRUE, - EntityPublishedInterface::class => FALSE, - ], - 'entity_type', - ['collection' => TRUE]); - - $expected_permissions = [ - 'administer blue_entity' => 'Administer blue entities', - 'access blue_entity overview' => 'Access the blue entities overview page', - 'create blue_entity' => 'Create blue entities', - 'update any blue_entity' => 'Update any blue entity', - 'update own blue_entity' => 'Update own blue entities', - 'delete any blue_entity' => 'Delete any blue entity', - 'delete own blue_entity' => 'Delete own blue entities', - 'view blue_entity' => 'View blue entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // Content entity type with bundles. - - $entity_type = $this->prophesizeEntityType( - 'white', - [ - EntityOwnerInterface::class => FALSE, - EntityPublishedInterface::class => FALSE, - ], - 'bundle', - ['collection' => TRUE]); - - $expected_permissions = [ - 'administer white_entity' => 'Administer white entities', - 'access white_entity overview' => 'Access the white entities overview page', - 'create first white_entity' => 'First: Create white entities', - 'update first white_entity' => 'First: Update white entities', - 'delete first white_entity' => 'First: Delete white entities', - 'create second white_entity' => 'Second: Create white entities', - 'update second white_entity' => 'Second: Update white entities', - 'delete second white_entity' => 'Second: Delete white entities', - 'view white_entity' => 'View white entities', - 'view first white_entity' => 'First: View white entities', - 'view second white_entity' => 'Second: View white entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // Content entity type with bundles and owner. - - $entity_type = $this->prophesizeEntityType( - 'black', - [ - EntityOwnerInterface::class => TRUE, - EntityPublishedInterface::class => FALSE, - ], - 'bundle', - ['collection' => TRUE]); - - - $expected_permissions = [ - 'administer black_entity' => 'Administer black entities', - 'access black_entity overview' => 'Access the black entities overview page', - 'create third black_entity' => 'Third: Create black entities', - 'update any third black_entity' => 'Third: Update any black entity', - 'update own third black_entity' => 'Third: Update own black entities', - 'delete any third black_entity' => 'Third: Delete any black entity', - 'delete own third black_entity' => 'Third: Delete own black entities', - 'view black_entity' => 'View black entities', - 'view third black_entity' => 'Third: View black entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // Content entity type with bundles and owner and entity published. - - $entity_type = $this->prophesizeEntityType( - 'pink', - [ - EntityOwnerInterface::class => TRUE, - EntityPublishedInterface::class => TRUE, - ], - 'bundle', - ['collection' => TRUE]); - - $expected_permissions = [ - 'administer pink_entity' => 'Administer pink entities', - 'access pink_entity overview' => 'Access the pink entities overview page', - 'view own unpublished pink_entity' => 'View own unpublished pink entities', - 'create third pink_entity' => 'Third: Create pink entities', - 'update any third pink_entity' => 'Third: Update any pink entity', - 'update own third pink_entity' => 'Third: Update own pink entities', - 'delete any third pink_entity' => 'Third: Delete any pink entity', - 'delete own third pink_entity' => 'Third: Delete own pink entities', - 'view pink_entity' => 'View pink entities', - 'view third pink_entity' => 'Third: View pink entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // content entity type without overview page - $entity_type = $this->prophesizeEntityType( - 'orange', - [ - EntityOwnerInterface::class => FALSE, - EntityPublishedInterface::class => FALSE, - ], - 'entity_type', - ['collection' => FALSE]); - $expected_permissions = [ - 'administer orange_entity' => 'Administer orange entities', - 'create orange_entity' => 'Create orange entities', - 'update orange_entity' => 'Update orange entities', - 'delete orange_entity' => 'Delete orange entities', - 'view orange_entity' => 'View orange entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - - return $data; - } - - /** - * Create a prophesized entity type object - * - * @param string $base_name - * @param array $implementations - * @param string $permission_granularity - * @param array $link_templates - * - * @return \Prophecy\Prophecy\ObjectProphecy - */ - protected function prophesizeEntityType(string $base_name, array $implementations, string $permission_granularity, array $link_templates): \Prophecy\Prophecy\ObjectProphecy { - $entity_type = $this->prophesize(ContentEntityTypeInterface::class); - $entity_type->getProvider()->willReturn('entity_module_test'); - $entity_type->id()->willReturn($base_name . '_entity'); - $entity_type->getSingularLabel()->willReturn($base_name . ' entity'); - $entity_type->getPluralLabel()->willReturn($base_name . ' entities'); - foreach ($implementations as $implementation => $value) { - $entity_type->entityClassImplements($implementation) - ->willReturn($value); - } - $entity_type->getPermissionGranularity() - ->willReturn($permission_granularity); - foreach ($link_templates as $linkTemplate => $value) { - $entity_type->hasLinkTemplate($linkTemplate)->willReturn($value); - } - return $entity_type; - } - -} diff --git a/core/tests/Drupal/Tests/Core/Entity/PermissionBasedEntityAccessControlHandlerTest.php b/core/tests/Drupal/Tests/Core/Entity/PermissionBasedEntityAccessControlHandlerTest.php deleted file mode 100644 index 8170eea..0000000 --- a/core/tests/Drupal/Tests/Core/Entity/PermissionBasedEntityAccessControlHandlerTest.php +++ /dev/null @@ -1,247 +0,0 @@ -prophesize(ModuleHandlerInterface::class); - $module_handler->invokeAll(Argument::any(), Argument::any())->willReturn([]); - $cache_contexts_manager = $this->prophesize(CacheContextsManager::class); - $cache_contexts_manager->assertValidTokens(Argument::any())->willReturn(TRUE); - - $container = new ContainerBuilder(); - $container->set('module_handler', $module_handler->reveal()); - $container->set('cache_contexts_manager', $cache_contexts_manager->reveal()); - \Drupal::setContainer($container); - } - - /** - * @covers ::checkAccess - * @covers ::checkEntityPermissions - * @covers ::checkEntityOwnerPermissions - * @covers ::checkCreateAccess - * - * @dataProvider accessProvider - */ - public function testAccess(EntityInterface $entity, $operation, $account, $allowed) { - $handler = new PermissionBasedEntityAccessControlHandler($entity->getEntityType()); - $handler->setStringTranslation($this->getStringTranslationStub()); - $result = $handler->access($entity, $operation, $account); - $this->assertEquals($allowed, $result); - } - - /** - * @covers ::checkCreateAccess - * - * @dataProvider createAccessProvider - */ - public function testCreateAccess(EntityTypeInterface $entity_type, $bundle, $account, $allowed) { - $handler = new PermissionBasedEntityAccessControlHandler($entity_type); - $handler->setStringTranslation($this->getStringTranslationStub()); - $result = $handler->createAccess($bundle, $account); - $this->assertEquals($allowed, $result); - } - - /** - * Data provider for testAccess(). - * - * @return array - * A list of testAccess method arguments. - */ - public function accessProvider() { - $entity_type = $this->prophesize(ContentEntityTypeInterface::class); - $entity_type->id()->willReturn('green_entity'); - $entity_type->getAdminPermission()->willReturn('administer green_entity'); - $entity_type->hasHandlerClass('permission_provider')->willReturn(TRUE); - $entity_type->getHandlerClass('permission_provider')->willReturn(EntityPermissionProvider::class); - $entity = $this->buildMockEntity($entity_type->reveal(), 6); - - $data = []; - // Admin permission. - $admin_user = $this->buildMockUser(5, 'administer green_entity'); - $data[] = [$entity->reveal(), 'view', $admin_user->reveal(), TRUE]; - $data[] = [$entity->reveal(), 'update', $admin_user->reveal(), TRUE]; - $data[] = [$entity->reveal(), 'delete', $admin_user->reveal(), TRUE]; - - // Update, delete, view permissions, entity without an owner. - $second_entity = $this->buildMockEntity($entity_type->reveal()); - foreach (['view', 'update', 'delete'] as $operation) { - $first_user = $this->buildMockUser(6, $operation . ' green_entity'); - $second_user = $this->buildMockUser(7, 'access content'); - - $data[] = [$second_entity->reveal(), $operation, $first_user->reveal(), TRUE]; - $data[] = [$second_entity->reveal(), $operation, $second_user->reveal(), FALSE]; - } - - // Update and delete permissions. - foreach (['update', 'delete'] as $operation) { - // Owner, non-owner, user with "any" permission. - $first_user = $this->buildMockUser(6, $operation . ' own green_entity'); - $second_user = $this->buildMockUser(7, $operation . ' own green_entity'); - $third_user = $this->buildMockUser(8, $operation . ' any green_entity'); - - $data[] = [$entity->reveal(), $operation, $first_user->reveal(), TRUE]; - $data[] = [$entity->reveal(), $operation, $second_user->reveal(), FALSE]; - $data[] = [$entity->reveal(), $operation, $third_user->reveal(), TRUE]; - } - - // View permissions. - $first_user = $this->buildMockUser(9, 'view green_entity'); - $second_user = $this->buildMockUser(10, 'view first green_entity'); - $third_user = $this->buildMockUser(14, 'view own unpublished green_entity'); - $fourth_user = $this->buildMockUser(14, 'access content'); - - $first_entity = $this->buildMockEntity($entity_type->reveal(), 1, 'first'); - $second_entity = $this->buildMockEntity($entity_type->reveal(), 1, 'second'); - $third_entity = $this->buildMockEntity($entity_type->reveal(), 14, 'first', FALSE); - - // The first user can view the two published entities. - $data[] = [$first_entity->reveal(), 'view', $first_user->reveal(), TRUE]; - $data[] = [$second_entity->reveal(), 'view', $first_user->reveal(), TRUE]; - $data[] = [$third_entity->reveal(), 'view', $first_user->reveal(), FALSE]; - - // The second user can only view published entities of bundle "first". - $data[] = [$first_entity->reveal(), 'view', $second_user->reveal(), TRUE]; - $data[] = [$second_entity->reveal(), 'view', $second_user->reveal(), FALSE]; - $data[] = [$third_entity->reveal(), 'view', $second_user->reveal(), FALSE]; - - // The third user can view their own unpublished entity. - $data[] = [$first_entity->reveal(), 'view', $third_user->reveal(), FALSE]; - $data[] = [$second_entity->reveal(), 'view', $third_user->reveal(), FALSE]; - $data[] = [$third_entity->reveal(), 'view', $third_user->reveal(), TRUE]; - - // The fourth user can't view anything. - $data[] = [$first_entity->reveal(), 'view', $fourth_user->reveal(), FALSE]; - $data[] = [$second_entity->reveal(), 'view', $fourth_user->reveal(), FALSE]; - $data[] = [$third_entity->reveal(), 'view', $fourth_user->reveal(), FALSE]; - - return $data; - } - - /** - * Data provider for testCreateAccess(). - * - * @return array - * A list of testCreateAccess method arguments. - */ - public function createAccessProvider() { - $data = []; - - $entity_type = $this->prophesize(ContentEntityTypeInterface::class); - $entity_type->id()->willReturn('green_entity'); - $entity_type->getAdminPermission()->willReturn('administer green_entity'); - $entity_type->hasHandlerClass('permission_provider')->willReturn(TRUE); - $entity_type->getHandlerClass('permission_provider')->willReturn(EntityPermissionProvider::class); - - // User with the admin permission. - $account = $this->prophesize(AccountInterface::class); - $account->id()->willReturn(6); - $account->hasPermission('administer green_entity')->willReturn(TRUE); - $data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE]; - - // Ordinary user. - $account = $this->prophesize(AccountInterface::class); - $account->id()->willReturn(6); - $account->hasPermission('create green_entity')->willReturn(TRUE); - $account->hasPermission(Argument::any())->willReturn(FALSE); - $data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE]; - - // Ordinary user, entity with a bundle. - $account = $this->prophesize(AccountInterface::class); - $account->id()->willReturn(6); - $account->hasPermission('create first_bundle green_entity')->willReturn(TRUE); - $account->hasPermission(Argument::any())->willReturn(FALSE); - $data[] = [$entity_type->reveal(), 'first_bundle', $account->reveal(), TRUE]; - - // User with no permissions. - $account = $this->prophesize(AccountInterface::class); - $account->id()->willReturn(6); - $account->hasPermission(Argument::any())->willReturn(FALSE); - $data[] = [$entity_type->reveal(), NULL, $account->reveal(), FALSE]; - - return $data; - } - - /** - * Builds a mock entity. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * @param string $owner_id - * The owner ID. - * @param string $bundle - * The entity bundle. - * @param bool $published - * The published status. - * - * @return \Prophecy\Prophecy\ObjectProphecy - * The entity mock. - */ - protected function buildMockEntity(EntityTypeInterface $entity_type, $owner_id = NULL, $bundle = NULL, $published = NULL) { - $langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED; - $entity = $this->prophesize(ContentEntityInterface::class); - if (isset($published)) { - $entity->willImplement(EntityPublishedInterface::class); - } - if ($owner_id) { - $entity->willImplement(EntityOwnerInterface::class); - } - if (isset($published)) { - $entity->isPublished()->willReturn($published); - } - if ($owner_id) { - $entity->getOwnerId()->willReturn($owner_id); - } - - $entity->bundle()->willReturn($bundle ?: $entity_type->id()); - $entity->isNew()->willReturn(FALSE); - $entity->uuid()->willReturn('fake uuid'); - $entity->id()->willReturn('fake id'); - $entity->getRevisionId()->willReturn('fake id'); - $entity->language()->willReturn(new Language(['id' => $langcode])); - $entity->getEntityTypeId()->willReturn($entity_type->id()); - $entity->getEntityType()->willReturn($entity_type); - $entity->getCacheContexts()->willReturn([]); - $entity->getCacheTags()->willReturn([]); - $entity->getCacheMaxAge()->willReturn(Cache::PERMANENT); - - return $entity; - } - - protected function buildMockUser($uid, $permission) { - $account = $this->prophesize(AccountInterface::class); - $account->id()->willReturn($uid); - $account->hasPermission($permission)->willReturn(TRUE); - $account->hasPermission(Argument::any())->willReturn(FALSE); - return $account; - } - -} diff --git a/core/tests/Drupal/Tests/Core/Entity/UncacheableEntityAccessControlHandlerTest.php b/core/tests/Drupal/Tests/Core/Entity/UncacheableEntityAccessControlHandlerTest.php deleted file mode 100644 index e855fbb..0000000 --- a/core/tests/Drupal/Tests/Core/Entity/UncacheableEntityAccessControlHandlerTest.php +++ /dev/null @@ -1,237 +0,0 @@ -prophesize(ModuleHandlerInterface::class); - $module_handler->invokeAll(Argument::any(), Argument::any())->willReturn([]); - $cache_contexts_manager = $this->prophesize(CacheContextsManager::class); - $cache_contexts_manager->assertValidTokens(Argument::any())->willReturn(TRUE); - - $container = new ContainerBuilder(); - $container->set('module_handler', $module_handler->reveal()); - $container->set('cache_contexts_manager', $cache_contexts_manager->reveal()); - \Drupal::setContainer($container); - } - - /** - * @covers ::checkAccess - * @covers ::checkEntityPermissions - * @covers ::checkEntityOwnerPermissions - * @covers ::checkCreateAccess - * - * @dataProvider accessProvider - */ - public function testAccess(EntityInterface $entity, $operation, $account, $allowed) { - $handler = new UncacheableEntityAccessControlHandler($entity->getEntityType()); - $handler->setStringTranslation($this->getStringTranslationStub()); - $result = $handler->access($entity, $operation, $account); - $this->assertEquals($allowed, $result); - } - - /** - * @covers ::checkCreateAccess - * - * @dataProvider createAccessProvider - */ - public function testCreateAccess(EntityTypeInterface $entity_type, $bundle, $account, $allowed) { - $handler = new UncacheableEntityAccessControlHandler($entity_type); - $handler->setStringTranslation($this->getStringTranslationStub()); - $result = $handler->createAccess($bundle, $account); - $this->assertEquals($allowed, $result); - } - - /** - * Data provider for testAccess(). - * - * @return array - * A list of testAccess method arguments. - */ - public function accessProvider() { - $entity_type = $this->prophesize(ContentEntityTypeInterface::class); - $entity_type->id()->willReturn('green_entity'); - $entity_type->getAdminPermission()->willReturn('administer green_entity'); - $entity_type->hasHandlerClass('permission_provider')->willReturn(TRUE); - $entity_type->getHandlerClass('permission_provider')->willReturn(UncacheableEntityPermissionProvider::class); - $entity = $this->buildMockEntity($entity_type->reveal(), 6); - - $data = []; - // Admin permission. - $admin_user = $this->buildMockUser(5, 'administer green_entity'); - $data[] = [$entity->reveal(), 'view', $admin_user->reveal(), TRUE]; - $data[] = [$entity->reveal(), 'update', $admin_user->reveal(), TRUE]; - $data[] = [$entity->reveal(), 'delete', $admin_user->reveal(), TRUE]; - - // View, update, delete permissions, entity without an owner. - $second_entity = $this->buildMockEntity($entity_type->reveal()); - foreach (['view', 'update', 'delete'] as $operation) { - $first_user = $this->buildMockUser(6, $operation . ' green_entity'); - $second_user = $this->buildMockUser(7, 'access content'); - - $data[] = [$second_entity->reveal(), $operation, $first_user->reveal(), TRUE]; - $data[] = [$second_entity->reveal(), $operation, $second_user->reveal(), FALSE]; - } - - // View, update, delete permissions. - foreach (['view', 'update', 'delete'] as $operation) { - // Owner, non-owner, user with "any" permission. - $first_user = $this->buildMockUser(6, $operation . ' own green_entity'); - $second_user = $this->buildMockUser(7, $operation . ' own green_entity'); - $third_user = $this->buildMockUser(8, $operation . ' any green_entity'); - - $data[] = [$entity->reveal(), $operation, $first_user->reveal(), TRUE]; - $data[] = [$entity->reveal(), $operation, $second_user->reveal(), FALSE]; - $data[] = [$entity->reveal(), $operation, $third_user->reveal(), TRUE]; - } - - // Per bundle and unpublished view permissions. - $first_user = $this->buildMockUser(11, 'view any first green_entity'); - $second_user = $this->buildMockUser(12, 'view own first green_entity'); - $third_user = $this->buildMockUser(13, 'view own unpublished green_entity'); - - $first_entity = $this->buildMockEntity($entity_type->reveal(), 9999, 'first'); - $second_entity = $this->buildMockEntity($entity_type->reveal(), 12, 'first'); - $third_entity = $this->buildMockEntity($entity_type->reveal(), 9999, 'second'); - $fourth_entity = $this->buildMockEntity($entity_type->reveal(), 10, 'second'); - $fifth_entity = $this->buildMockEntity($entity_type->reveal(), 13, 'first', FALSE); - - // The first user can view the two entities of bundle "first". - $data[] = [$first_entity->reveal(), 'view', $first_user->reveal(), TRUE]; - $data[] = [$second_entity->reveal(), 'view', $first_user->reveal(), TRUE]; - $data[] = [$third_entity->reveal(), 'view', $first_user->reveal(), FALSE]; - $data[] = [$fourth_entity->reveal(), 'view', $first_user->reveal(), FALSE]; - $data[] = [$fifth_entity->reveal(), 'view', $first_user->reveal(), FALSE]; - - // The second user can view their own entity of bundle "first". - $data[] = [$first_entity->reveal(), 'view', $second_user->reveal(), FALSE]; - $data[] = [$second_entity->reveal(), 'view', $second_user->reveal(), TRUE]; - $data[] = [$third_entity->reveal(), 'view', $second_user->reveal(), FALSE]; - $data[] = [$fourth_entity->reveal(), 'view', $second_user->reveal(), FALSE]; - $data[] = [$fourth_entity->reveal(), 'view', $second_user->reveal(), FALSE]; - $data[] = [$fifth_entity->reveal(), 'view', $second_user->reveal(), FALSE]; - - // The third user can only view their own unpublished entity. - $data[] = [$first_entity->reveal(), 'view', $third_user->reveal(), FALSE]; - $data[] = [$second_entity->reveal(), 'view', $third_user->reveal(), FALSE]; - $data[] = [$third_entity->reveal(), 'view', $third_user->reveal(), FALSE]; - $data[] = [$fourth_entity->reveal(), 'view', $third_user->reveal(), FALSE]; - $data[] = [$fourth_entity->reveal(), 'view', $third_user->reveal(), FALSE]; - $data[] = [$fifth_entity->reveal(), 'view', $third_user->reveal(), TRUE]; - - return $data; - } - - /** - * Data provider for testCreateAccess(). - * - * @return array - * A list of testCreateAccess method arguments. - */ - public function createAccessProvider() { - $data = []; - - $entity_type = $this->prophesize(ContentEntityTypeInterface::class); - $entity_type->id()->willReturn('green_entity'); - $entity_type->getAdminPermission()->willReturn('administer green_entity'); - $entity_type->hasHandlerClass('permission_provider')->willReturn(TRUE); - $entity_type->getHandlerClass('permission_provider')->willReturn(UncacheableEntityPermissionProvider::class); - - // User with the admin permission. - $account = $this->buildMockUser('6', 'administer green_entity'); - $data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE]; - - // Ordinary user. - $account = $this->buildMockUser('6', 'create green_entity'); - $data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE]; - - // Ordinary user, entity with a bundle. - $account = $this->buildMockUser('6', 'create first_bundle green_entity'); - $data[] = [$entity_type->reveal(), 'first_bundle', $account->reveal(), TRUE]; - - // User with no permissions. - $account = $this->buildMockUser('6', 'access content'); - $data[] = [$entity_type->reveal(), NULL, $account->reveal(), FALSE]; - - return $data; - } - - /** - * Builds a mock entity. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * @param string $owner_id - * The owner ID. - * - * @return \Prophecy\Prophecy\ObjectProphecy - * The entity mock. - */ - protected function buildMockEntity(EntityTypeInterface $entity_type, $owner_id = NULL, $bundle = NULL, $published = NULL) { - $langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED; - $entity = $this->prophesize(ContentEntityInterface::class); - if (isset($published)) { - $entity->willImplement(EntityPublishedInterface::class); - } - if ($owner_id) { - $entity->willImplement(EntityOwnerInterface::class); - } - if (isset($published)) { - $entity->isPublished()->willReturn($published); - } - if ($owner_id) { - $entity->getOwnerId()->willReturn($owner_id); - } - - $entity->bundle()->willReturn($bundle ?: $entity_type->id()); - $entity->isNew()->willReturn(FALSE); - $entity->uuid()->willReturn('fake uuid'); - $entity->id()->willReturn('fake id'); - $entity->getRevisionId()->willReturn(NULL); - $entity->language()->willReturn(new Language(['id' => $langcode])); - $entity->getEntityTypeId()->willReturn($entity_type->id()); - $entity->getEntityType()->willReturn($entity_type); - $entity->getCacheContexts()->willReturn([]); - $entity->getCacheTags()->willReturn([]); - $entity->getCacheMaxAge()->willReturn(Cache::PERMANENT); - - return $entity; - } - - protected function buildMockUser($uid, $permission) { - $account = $this->prophesize(AccountInterface::class); - $account->id()->willReturn($uid); - $account->hasPermission($permission)->willReturn(TRUE); - $account->hasPermission(Argument::any())->willReturn(FALSE); - return $account; - } - -} diff --git a/core/tests/Drupal/Tests/Core/Entity/UncacheableEntityPermissionProviderTest.php b/core/tests/Drupal/Tests/Core/Entity/UncacheableEntityPermissionProviderTest.php deleted file mode 100644 index b1461ec..0000000 --- a/core/tests/Drupal/Tests/Core/Entity/UncacheableEntityPermissionProviderTest.php +++ /dev/null @@ -1,184 +0,0 @@ -prophesize(EntityTypeBundleInfoInterface::class); - $entity_type_bundle_info->getBundleInfo('white_entity')->willReturn([ - 'first' => ['label' => 'First'], - 'second' => ['label' => 'Second'], - ]); - $entity_type_bundle_info->getBundleInfo('black_entity')->willReturn([ - 'third' => ['label' => 'Third'], - ]); - $entity_type_bundle_info->getBundleInfo('pink_entity')->willReturn([ - 'third' => ['label' => 'Third'], - ]); - $this->permissionProvider = new UncacheableEntityPermissionProvider($entity_type_bundle_info->reveal()); - $this->permissionProvider->setStringTranslation($this->getStringTranslationStub()); - } - - - /** - * Data provider for testBuildPermissions(). - * - * @return array - * A list of testBuildPermissions method arguments. - */ - public function entityTypeProvider() { - $data = []; - // Content entity type. - $entity_type = $this->prophesizeEntityType( - 'green', - [ - EntityOwnerInterface::class => FALSE, - EntityPublishedInterface::class => FALSE, - ], - 'entity_type', - ['collection' => TRUE]); - $expected_permissions = [ - 'administer green_entity' => 'Administer green entities', - 'access green_entity overview' => 'Access the green entities overview page', - 'create green_entity' => 'Create green entities', - 'update green_entity' => 'Update green entities', - 'delete green_entity' => 'Delete green entities', - 'view any green_entity' => 'View any green entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // Content entity type with owner. - $entity_type = $this->prophesizeEntityType( - 'blue', - [ - EntityOwnerInterface::class => TRUE, - EntityPublishedInterface::class => FALSE, - ], - 'entity_type', - ['collection' => TRUE]); - $expected_permissions = [ - 'administer blue_entity' => 'Administer blue entities', - 'access blue_entity overview' => 'Access the blue entities overview page', - 'create blue_entity' => 'Create blue entities', - 'update any blue_entity' => 'Update any blue entity', - 'update own blue_entity' => 'Update own blue entities', - 'delete any blue_entity' => 'Delete any blue entity', - 'delete own blue_entity' => 'Delete own blue entities', - 'view any blue_entity' => 'View any blue entities', - 'view own blue_entity' => 'View own blue entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // Content entity type with bundles. - $entity_type = $this->prophesizeEntityType( - 'white', - [ - EntityOwnerInterface::class => FALSE, - EntityPublishedInterface::class => FALSE, - ], - 'bundle', - ['collection' => TRUE]); - $expected_permissions = [ - 'administer white_entity' => 'Administer white entities', - 'access white_entity overview' => 'Access the white entities overview page', - 'create first white_entity' => 'First: Create white entities', - 'update first white_entity' => 'First: Update white entities', - 'delete first white_entity' => 'First: Delete white entities', - 'create second white_entity' => 'Second: Create white entities', - 'update second white_entity' => 'Second: Update white entities', - 'delete second white_entity' => 'Second: Delete white entities', - 'view any white_entity' => 'View any white entities', - 'view any first white_entity' => 'First: View any white entities', - 'view any second white_entity' => 'Second: View any white entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // Content entity type with bundles and owner. - $entity_type = $this->prophesizeEntityType( - 'black', - [ - EntityOwnerInterface::class => TRUE, - EntityPublishedInterface::class => FALSE, - ], - 'bundle', - ['collection' => TRUE]); - $expected_permissions = [ - 'administer black_entity' => 'Administer black entities', - 'access black_entity overview' => 'Access the black entities overview page', - 'create third black_entity' => 'Third: Create black entities', - 'update any third black_entity' => 'Third: Update any black entity', - 'update own third black_entity' => 'Third: Update own black entities', - 'delete any third black_entity' => 'Third: Delete any black entity', - 'delete own third black_entity' => 'Third: Delete own black entities', - 'view any black_entity' => 'View any black entities', - 'view own black_entity' => 'View own black entities', - 'view any third black_entity' => 'Third: View any black entities', - 'view own third black_entity' => 'Third: View own black entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // Content entity type with bundles and owner and entity published. - $entity_type = $this->prophesizeEntityType( - 'pink', - [ - EntityOwnerInterface::class => TRUE, - EntityPublishedInterface::class => TRUE, - ], - 'bundle', - ['collection' => TRUE]); - $expected_permissions = [ - 'administer pink_entity' => 'Administer pink entities', - 'access pink_entity overview' => 'Access the pink entities overview page', - 'view own unpublished pink_entity' => 'View own unpublished pink entities', - 'create third pink_entity' => 'Third: Create pink entities', - 'update any third pink_entity' => 'Third: Update any pink entity', - 'update own third pink_entity' => 'Third: Update own pink entities', - 'delete any third pink_entity' => 'Third: Delete any pink entity', - 'delete own third pink_entity' => 'Third: Delete own pink entities', - 'view any pink_entity' => 'View any pink entities', - 'view own pink_entity' => 'View own pink entities', - 'view any third pink_entity' => 'Third: View any pink entities', - 'view own third pink_entity' => 'Third: View own pink entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - // content entity type without overview page - $entity_type = $this->prophesizeEntityType( - 'orange', - [ - EntityOwnerInterface::class => FALSE, - EntityPublishedInterface::class => FALSE, - ], - 'entity_type', - ['collection' => FALSE]); - $expected_permissions = [ - 'administer orange_entity' => 'Administer orange entities', - 'create orange_entity' => 'Create orange entities', - 'update orange_entity' => 'Update orange entities', - 'delete orange_entity' => 'Delete orange entities', - 'view any orange_entity' => 'View any orange entities', - ]; - $data[] = [$entity_type->reveal(), $expected_permissions]; - - return $data; - } - -}