LatestRevisionCheckTest.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <?php
  2. namespace Drupal\Tests\content_moderation\Unit;
  3. use Drupal\block_content\Entity\BlockContent;
  4. use Drupal\Core\Access\AccessResultAllowed;
  5. use Drupal\Core\Access\AccessResultForbidden;
  6. use Drupal\Core\Access\AccessResultNeutral;
  7. use Drupal\Core\Cache\Context\CacheContextsManager;
  8. use Drupal\Core\Routing\RouteMatch;
  9. use Drupal\Core\Session\AccountInterface;
  10. use Drupal\node\Entity\Node;
  11. use Drupal\content_moderation\Access\LatestRevisionCheck;
  12. use Drupal\content_moderation\ModerationInformation;
  13. use Drupal\Tests\UnitTestCase;
  14. use Drupal\user\EntityOwnerInterface;
  15. use Prophecy\Argument;
  16. use Symfony\Component\DependencyInjection\ContainerBuilder;
  17. use Symfony\Component\Routing\Route;
  18. /**
  19. * @coversDefaultClass \Drupal\content_moderation\Access\LatestRevisionCheck
  20. * @group content_moderation
  21. */
  22. class LatestRevisionCheckTest extends UnitTestCase {
  23. /**
  24. * {@inheritdoc}
  25. */
  26. protected function setUp() {
  27. parent::setUp();
  28. // Initialize Drupal container since the cache context manager is needed.
  29. $contexts_manager = $this->prophesize(CacheContextsManager::class);
  30. $contexts_manager->assertValidTokens(Argument::any())->willReturn(TRUE);
  31. $builder = new ContainerBuilder();
  32. $builder->set('cache_contexts_manager', $contexts_manager->reveal());
  33. \Drupal::setContainer($builder);
  34. }
  35. /**
  36. * Test the access check of the LatestRevisionCheck service.
  37. *
  38. * @param string $entity_class
  39. * The class of the entity to mock.
  40. * @param string $entity_type
  41. * The machine name of the entity to mock.
  42. * @param bool $has_pending_revision
  43. * Whether this entity should have a pending revision in the system.
  44. * @param array $account_permissions
  45. * An array of permissions the account has.
  46. * @param bool $is_owner
  47. * Indicates if the user should be the owner of the entity.
  48. * @param string $result_class
  49. * The AccessResult class that should result. One of AccessResultAllowed,
  50. * AccessResultForbidden, AccessResultNeutral.
  51. *
  52. * @dataProvider accessSituationProvider
  53. */
  54. public function testLatestAccessPermissions($entity_class, $entity_type, $has_pending_revision, array $account_permissions, $is_owner, $result_class) {
  55. /** @var \Drupal\Core\Session\AccountInterface $account */
  56. $account = $this->prophesize(AccountInterface::class);
  57. $possible_permissions = [
  58. 'view latest version',
  59. 'view any unpublished content',
  60. 'view own unpublished content',
  61. ];
  62. foreach ($possible_permissions as $permission) {
  63. $account->hasPermission($permission)->willReturn(in_array($permission, $account_permissions));
  64. }
  65. $account->id()->willReturn(42);
  66. /** @var \Drupal\Core\Entity\EntityInterface $entity */
  67. $entity = $this->prophesize($entity_class);
  68. $entity->getCacheContexts()->willReturn([]);
  69. $entity->getCacheTags()->willReturn([]);
  70. $entity->getCacheMaxAge()->willReturn(0);
  71. if (is_subclass_of($entity_class, EntityOwnerInterface::class)) {
  72. $entity->getOwnerId()->willReturn($is_owner ? 42 : 3);
  73. }
  74. /** @var \Drupal\content_moderation\ModerationInformation $mod_info */
  75. $mod_info = $this->prophesize(ModerationInformation::class);
  76. $mod_info->hasPendingRevision($entity->reveal())->willReturn($has_pending_revision);
  77. $route = $this->prophesize(Route::class);
  78. $route->getOption('_content_moderation_entity_type')->willReturn($entity_type);
  79. $route_match = $this->prophesize(RouteMatch::class);
  80. $route_match->getParameter($entity_type)->willReturn($entity->reveal());
  81. $lrc = new LatestRevisionCheck($mod_info->reveal());
  82. /** @var \Drupal\Core\Access\AccessResult $result */
  83. $result = $lrc->access($route->reveal(), $route_match->reveal(), $account->reveal());
  84. $this->assertInstanceOf($result_class, $result);
  85. }
  86. /**
  87. * Data provider for testLastAccessPermissions().
  88. */
  89. public function accessSituationProvider() {
  90. return [
  91. // Node with global permissions and latest version.
  92. [Node::class, 'node', TRUE, ['view latest version', 'view any unpublished content'], FALSE, AccessResultAllowed::class],
  93. // Node with global permissions and no latest version.
  94. [Node::class, 'node', FALSE, ['view latest version', 'view any unpublished content'], FALSE, AccessResultForbidden::class],
  95. // Node with own content permissions and latest version.
  96. [Node::class, 'node', TRUE, ['view latest version', 'view own unpublished content'], TRUE, AccessResultAllowed::class],
  97. // Node with own content permissions and no latest version.
  98. [Node::class, 'node', FALSE, ['view latest version', 'view own unpublished content'], FALSE, AccessResultForbidden::class],
  99. // Node with own content permissions and latest version, but no perms to
  100. // view latest version.
  101. [Node::class, 'node', TRUE, ['view own unpublished content'], TRUE, AccessResultNeutral::class],
  102. // Node with own content permissions and no latest version, but no perms
  103. // to view latest version.
  104. [Node::class, 'node', TRUE, ['view own unpublished content'], FALSE, AccessResultNeutral::class],
  105. // Block with pending revision, and permissions to view any.
  106. [BlockContent::class, 'block_content', TRUE, ['view latest version', 'view any unpublished content'], FALSE, AccessResultAllowed::class],
  107. // Block with no pending revision.
  108. [BlockContent::class, 'block_content', FALSE, ['view latest version', 'view any unpublished content'], FALSE, AccessResultForbidden::class],
  109. // Block with pending revision, but no permission to view any.
  110. [BlockContent::class, 'block_content', TRUE, ['view latest version', 'view own unpublished content'], FALSE, AccessResultNeutral::class],
  111. // Block with no pending revision.
  112. [BlockContent::class, 'block_content', FALSE, ['view latest version', 'view own unpublished content'], FALSE, AccessResultForbidden::class],
  113. ];
  114. }
  115. }