Added Entity and Entity Reference Revisions which got dropped somewhere along the...
[yaffs-website] / web / modules / contrib / entity / tests / src / Unit / UncacheableEntityAccessControlHandlerTest.php
1 <?php
2
3 namespace Drupal\Tests\entity\Unit;
4
5 use Drupal\Core\Cache\Cache;
6 use Drupal\Core\Cache\Context\CacheContextsManager;
7 use Drupal\Core\DependencyInjection\ContainerBuilder;
8 use Drupal\Core\Entity\ContentEntityInterface;
9 use Drupal\Core\Entity\ContentEntityTypeInterface;
10 use Drupal\Core\Entity\EntityInterface;
11 use Drupal\Core\Entity\EntityPublishedInterface;
12 use Drupal\Core\Entity\EntityTypeInterface;
13 use Drupal\Core\Extension\ModuleHandlerInterface;
14 use Drupal\Core\Language\Language;
15 use Drupal\Core\Language\LanguageInterface;
16 use Drupal\Core\Session\AccountInterface;
17 use Drupal\entity\UncacheableEntityAccessControlHandler;
18 use Drupal\entity\UncacheableEntityPermissionProvider;
19 use Drupal\Tests\UnitTestCase;
20 use Drupal\user\EntityOwnerInterface;
21 use Prophecy\Argument;
22
23 /**
24  * @coversDefaultClass \Drupal\entity\UncacheableEntityAccessControlHandler
25  * @group entity
26  */
27 class UncacheableEntityAccessControlHandlerTest extends UnitTestCase {
28
29   /**
30    * {@inheritdoc}
31    */
32   protected function setUp() {
33     parent::setUp();
34
35     $module_handler = $this->prophesize(ModuleHandlerInterface::class);
36     $module_handler->invokeAll(Argument::any(), Argument::any())->willReturn([]);
37     $cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
38     $cache_contexts_manager->assertValidTokens(Argument::any())->willReturn(TRUE);
39
40     $container = new ContainerBuilder();
41     $container->set('module_handler', $module_handler->reveal());
42     $container->set('cache_contexts_manager', $cache_contexts_manager->reveal());
43     \Drupal::setContainer($container);
44   }
45
46   /**
47    * @covers ::checkAccess
48    * @covers ::checkEntityPermissions
49    * @covers ::checkEntityOwnerPermissions
50    * @covers ::checkCreateAccess
51    *
52    * @dataProvider accessProvider
53    */
54   public function testAccess(EntityInterface $entity, $operation, $account, $allowed) {
55     $handler = new UncacheableEntityAccessControlHandler($entity->getEntityType());
56     $handler->setStringTranslation($this->getStringTranslationStub());
57     $result = $handler->access($entity, $operation, $account);
58     $this->assertEquals($allowed, $result);
59   }
60
61   /**
62    * @covers ::checkCreateAccess
63    *
64    * @dataProvider createAccessProvider
65    */
66   public function testCreateAccess(EntityTypeInterface $entity_type, $bundle, $account, $allowed) {
67     $handler = new UncacheableEntityAccessControlHandler($entity_type);
68     $handler->setStringTranslation($this->getStringTranslationStub());
69     $result = $handler->createAccess($bundle, $account);
70     $this->assertEquals($allowed, $result);
71   }
72
73   /**
74    * Data provider for testAccess().
75    *
76    * @return array
77    *   A list of testAccess method arguments.
78    */
79   public function accessProvider() {
80     $entity_type = $this->prophesize(ContentEntityTypeInterface::class);
81     $entity_type->id()->willReturn('green_entity');
82     $entity_type->getAdminPermission()->willReturn('administer green_entity');
83     $entity_type->hasHandlerClass('permission_provider')->willReturn(TRUE);
84     $entity_type->getHandlerClass('permission_provider')->willReturn(UncacheableEntityPermissionProvider::class);
85     $entity = $this->buildMockEntity($entity_type->reveal(), 6);
86
87     $data = [];
88     // Admin permission.
89     $admin_user = $this->buildMockUser(5, 'administer green_entity');
90     $data[] = [$entity->reveal(), 'view', $admin_user->reveal(), TRUE];
91     $data[] = [$entity->reveal(), 'update', $admin_user->reveal(), TRUE];
92     $data[] = [$entity->reveal(), 'delete', $admin_user->reveal(), TRUE];
93
94     // View, update, delete permissions, entity without an owner.
95     $second_entity = $this->buildMockEntity($entity_type->reveal());
96     foreach (['view', 'update', 'delete'] as $operation) {
97       $first_user = $this->buildMockUser(6, $operation . ' green_entity');
98       $second_user = $this->buildMockUser(7, 'access content');
99
100       $data[] = [$second_entity->reveal(), $operation, $first_user->reveal(), TRUE];
101       $data[] = [$second_entity->reveal(), $operation, $second_user->reveal(), FALSE];
102     }
103
104     // View, update, delete permissions.
105     foreach (['view', 'update', 'delete'] as $operation) {
106       // Owner, non-owner, user with "any" permission.
107       $first_user = $this->buildMockUser(6, $operation . ' own green_entity');
108       $second_user = $this->buildMockUser(7, $operation . ' own green_entity');
109       $third_user = $this->buildMockUser(8, $operation . ' any green_entity');
110
111       $data[] = [$entity->reveal(), $operation, $first_user->reveal(), TRUE];
112       $data[] = [$entity->reveal(), $operation, $second_user->reveal(), FALSE];
113       $data[] = [$entity->reveal(), $operation, $third_user->reveal(), TRUE];
114     }
115
116     // Per bundle and unpublished view permissions.
117     $first_user = $this->buildMockUser(11, 'view any first green_entity');
118     $second_user = $this->buildMockUser(12, 'view own first green_entity');
119     $third_user = $this->buildMockUser(13, 'view own unpublished green_entity');
120
121     $first_entity = $this->buildMockEntity($entity_type->reveal(), 9999, 'first');
122     $second_entity = $this->buildMockEntity($entity_type->reveal(), 12, 'first');
123     $third_entity = $this->buildMockEntity($entity_type->reveal(), 9999, 'second');
124     $fourth_entity = $this->buildMockEntity($entity_type->reveal(), 10, 'second');
125     $fifth_entity = $this->buildMockEntity($entity_type->reveal(), 13, 'first', FALSE);
126
127     // The first user can view the two entities of bundle "first".
128     $data[] = [$first_entity->reveal(), 'view', $first_user->reveal(), TRUE];
129     $data[] = [$second_entity->reveal(), 'view', $first_user->reveal(), TRUE];
130     $data[] = [$third_entity->reveal(), 'view', $first_user->reveal(), FALSE];
131     $data[] = [$fourth_entity->reveal(), 'view', $first_user->reveal(), FALSE];
132     $data[] = [$fifth_entity->reveal(), 'view', $first_user->reveal(), FALSE];
133
134     // The second user can view their own entity of bundle "first".
135     $data[] = [$first_entity->reveal(), 'view', $second_user->reveal(), FALSE];
136     $data[] = [$second_entity->reveal(), 'view', $second_user->reveal(), TRUE];
137     $data[] = [$third_entity->reveal(), 'view', $second_user->reveal(), FALSE];
138     $data[] = [$fourth_entity->reveal(), 'view', $second_user->reveal(), FALSE];
139     $data[] = [$fourth_entity->reveal(), 'view', $second_user->reveal(), FALSE];
140     $data[] = [$fifth_entity->reveal(), 'view', $second_user->reveal(), FALSE];
141
142     // The third user can only view their own unpublished entity.
143     $data[] = [$first_entity->reveal(), 'view', $third_user->reveal(), FALSE];
144     $data[] = [$second_entity->reveal(), 'view', $third_user->reveal(), FALSE];
145     $data[] = [$third_entity->reveal(), 'view', $third_user->reveal(), FALSE];
146     $data[] = [$fourth_entity->reveal(), 'view', $third_user->reveal(), FALSE];
147     $data[] = [$fourth_entity->reveal(), 'view', $third_user->reveal(), FALSE];
148     $data[] = [$fifth_entity->reveal(), 'view', $third_user->reveal(), TRUE];
149
150     return $data;
151   }
152
153   /**
154    * Data provider for testCreateAccess().
155    *
156    * @return array
157    *   A list of testCreateAccess method arguments.
158    */
159   public function createAccessProvider() {
160     $data = [];
161
162     $entity_type = $this->prophesize(ContentEntityTypeInterface::class);
163     $entity_type->id()->willReturn('green_entity');
164     $entity_type->getAdminPermission()->willReturn('administer green_entity');
165     $entity_type->hasHandlerClass('permission_provider')->willReturn(TRUE);
166     $entity_type->getHandlerClass('permission_provider')->willReturn(UncacheableEntityPermissionProvider::class);
167
168     // User with the admin permission.
169     $account = $this->buildMockUser('6', 'administer green_entity');
170     $data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE];
171
172     // Ordinary user.
173     $account = $this->buildMockUser('6', 'create green_entity');
174     $data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE];
175
176     // Ordinary user, entity with a bundle.
177     $account = $this->buildMockUser('6', 'create first_bundle green_entity');
178     $data[] = [$entity_type->reveal(), 'first_bundle', $account->reveal(), TRUE];
179
180     // User with no permissions.
181     $account = $this->buildMockUser('6', 'access content');
182     $data[] = [$entity_type->reveal(), NULL, $account->reveal(), FALSE];
183
184     return $data;
185   }
186
187   /**
188    * Builds a mock entity.
189    *
190    * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
191    *   The entity type.
192    * @param string $owner_id
193    *   The owner ID.
194    * @param string $bundle
195    *   The bundle.
196    * @param bool $published
197    *   Whether the entity is published.
198    *
199    * @return \Prophecy\Prophecy\ObjectProphecy
200    *   The entity mock.
201    */
202   protected function buildMockEntity(EntityTypeInterface $entity_type, $owner_id = NULL, $bundle = NULL, $published = NULL) {
203     $langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED;
204     $entity = $this->prophesize(ContentEntityInterface::class);
205     if (isset($published)) {
206       $entity->willImplement(EntityPublishedInterface::class);
207     }
208     if ($owner_id) {
209       $entity->willImplement(EntityOwnerInterface::class);
210     }
211     if (isset($published)) {
212       $entity->isPublished()->willReturn($published);
213     }
214     if ($owner_id) {
215       $entity->getOwnerId()->willReturn($owner_id);
216     }
217
218     $entity->bundle()->willReturn($bundle ?: $entity_type->id());
219     $entity->isNew()->willReturn(FALSE);
220     $entity->uuid()->willReturn('fake uuid');
221     $entity->id()->willReturn('fake id');
222     $entity->getRevisionId()->willReturn(NULL);
223     $entity->language()->willReturn(new Language(['id' => $langcode]));
224     $entity->getEntityTypeId()->willReturn($entity_type->id());
225     $entity->getEntityType()->willReturn($entity_type);
226     $entity->getCacheContexts()->willReturn([]);
227     $entity->getCacheTags()->willReturn([]);
228     $entity->getCacheMaxAge()->willReturn(Cache::PERMANENT);
229
230     return $entity;
231   }
232
233   /**
234    * Builds a mock user.
235    *
236    * @param int $uid
237    *   The user ID.
238    * @param string $permission
239    *   The permission to grant.
240    *
241    * @return \Prophecy\Prophecy\ObjectProphecy
242    *   The user mock.
243    */
244   protected function buildMockUser($uid, $permission) {
245     $account = $this->prophesize(AccountInterface::class);
246     $account->id()->willReturn($uid);
247     $account->hasPermission($permission)->willReturn(TRUE);
248     $account->hasPermission(Argument::any())->willReturn(FALSE);
249
250     return $account;
251   }
252
253 }