Chris@18
|
1 <?php
|
Chris@18
|
2
|
Chris@18
|
3 namespace Drupal\Tests\jsonapi\Functional;
|
Chris@18
|
4
|
Chris@18
|
5 use Drupal\comment\Entity\Comment;
|
Chris@18
|
6 use Drupal\comment\Entity\CommentType;
|
Chris@18
|
7 use Drupal\comment\Tests\CommentTestTrait;
|
Chris@18
|
8 use Drupal\Component\Serialization\Json;
|
Chris@18
|
9 use Drupal\Component\Utility\NestedArray;
|
Chris@18
|
10 use Drupal\Core\Cache\Cache;
|
Chris@18
|
11 use Drupal\Core\Entity\EntityInterface;
|
Chris@18
|
12 use Drupal\Core\Session\AccountInterface;
|
Chris@18
|
13 use Drupal\Core\Url;
|
Chris@18
|
14 use Drupal\entity_test\Entity\EntityTest;
|
Chris@18
|
15 use Drupal\Tests\jsonapi\Traits\CommonCollectionFilterAccessTestPatternsTrait;
|
Chris@18
|
16 use Drupal\user\Entity\User;
|
Chris@18
|
17 use GuzzleHttp\RequestOptions;
|
Chris@18
|
18
|
Chris@18
|
19 /**
|
Chris@18
|
20 * JSON:API integration test for the "Comment" content entity type.
|
Chris@18
|
21 *
|
Chris@18
|
22 * @group jsonapi
|
Chris@18
|
23 */
|
Chris@18
|
24 class CommentTest extends ResourceTestBase {
|
Chris@18
|
25
|
Chris@18
|
26 use CommentTestTrait;
|
Chris@18
|
27 use CommonCollectionFilterAccessTestPatternsTrait;
|
Chris@18
|
28
|
Chris@18
|
29 /**
|
Chris@18
|
30 * {@inheritdoc}
|
Chris@18
|
31 */
|
Chris@18
|
32 public static $modules = ['comment', 'entity_test'];
|
Chris@18
|
33
|
Chris@18
|
34 /**
|
Chris@18
|
35 * {@inheritdoc}
|
Chris@18
|
36 */
|
Chris@18
|
37 protected static $entityTypeId = 'comment';
|
Chris@18
|
38
|
Chris@18
|
39 /**
|
Chris@18
|
40 * {@inheritdoc}
|
Chris@18
|
41 */
|
Chris@18
|
42 protected static $resourceTypeName = 'comment--comment';
|
Chris@18
|
43
|
Chris@18
|
44 /**
|
Chris@18
|
45 * {@inheritdoc}
|
Chris@18
|
46 */
|
Chris@18
|
47 protected static $patchProtectedFieldNames = [
|
Chris@18
|
48 'status' => "The 'administer comments' permission is required.",
|
Chris@18
|
49 'name' => "The 'administer comments' permission is required.",
|
Chris@18
|
50 'homepage' => "The 'administer comments' permission is required.",
|
Chris@18
|
51 'created' => "The 'administer comments' permission is required.",
|
Chris@18
|
52 'changed' => NULL,
|
Chris@18
|
53 'thread' => NULL,
|
Chris@18
|
54 'entity_type' => NULL,
|
Chris@18
|
55 'field_name' => NULL,
|
Chris@18
|
56 // @todo Uncomment this after https://www.drupal.org/project/drupal/issues/1847608 lands. Until then, it's impossible to test this.
|
Chris@18
|
57 // 'pid' => NULL,
|
Chris@18
|
58 'uid' => "The 'administer comments' permission is required.",
|
Chris@18
|
59 'entity_id' => NULL,
|
Chris@18
|
60 ];
|
Chris@18
|
61
|
Chris@18
|
62 /**
|
Chris@18
|
63 * {@inheritdoc}
|
Chris@18
|
64 *
|
Chris@18
|
65 * @var \Drupal\comment\CommentInterface
|
Chris@18
|
66 */
|
Chris@18
|
67 protected $entity;
|
Chris@18
|
68
|
Chris@18
|
69 /**
|
Chris@18
|
70 * {@inheritdoc}
|
Chris@18
|
71 */
|
Chris@18
|
72 protected function setUpAuthorization($method) {
|
Chris@18
|
73 switch ($method) {
|
Chris@18
|
74 case 'GET':
|
Chris@18
|
75 $this->grantPermissionsToTestedRole(['access comments', 'view test entity']);
|
Chris@18
|
76 break;
|
Chris@18
|
77
|
Chris@18
|
78 case 'POST':
|
Chris@18
|
79 $this->grantPermissionsToTestedRole(['post comments']);
|
Chris@18
|
80 break;
|
Chris@18
|
81
|
Chris@18
|
82 case 'PATCH':
|
Chris@18
|
83 $this->grantPermissionsToTestedRole(['edit own comments']);
|
Chris@18
|
84 break;
|
Chris@18
|
85
|
Chris@18
|
86 case 'DELETE':
|
Chris@18
|
87 $this->grantPermissionsToTestedRole(['administer comments']);
|
Chris@18
|
88 break;
|
Chris@18
|
89 }
|
Chris@18
|
90 }
|
Chris@18
|
91
|
Chris@18
|
92 /**
|
Chris@18
|
93 * {@inheritdoc}
|
Chris@18
|
94 */
|
Chris@18
|
95 protected function createEntity() {
|
Chris@18
|
96 // Create a "bar" bundle for the "entity_test" entity type and create.
|
Chris@18
|
97 $bundle = 'bar';
|
Chris@18
|
98 entity_test_create_bundle($bundle, NULL, 'entity_test');
|
Chris@18
|
99
|
Chris@18
|
100 // Create a comment field on this bundle.
|
Chris@18
|
101 $this->addDefaultCommentField('entity_test', 'bar', 'comment');
|
Chris@18
|
102
|
Chris@18
|
103 // Create a "Camelids" test entity that the comment will be assigned to.
|
Chris@18
|
104 $commented_entity = EntityTest::create([
|
Chris@18
|
105 'name' => 'Camelids',
|
Chris@18
|
106 'type' => 'bar',
|
Chris@18
|
107 ]);
|
Chris@18
|
108 $commented_entity->save();
|
Chris@18
|
109
|
Chris@18
|
110 // Create a "Llama" comment.
|
Chris@18
|
111 $comment = Comment::create([
|
Chris@18
|
112 'comment_body' => [
|
Chris@18
|
113 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
|
Chris@18
|
114 'format' => 'plain_text',
|
Chris@18
|
115 ],
|
Chris@18
|
116 'entity_id' => $commented_entity->id(),
|
Chris@18
|
117 'entity_type' => 'entity_test',
|
Chris@18
|
118 'field_name' => 'comment',
|
Chris@18
|
119 ]);
|
Chris@18
|
120 $comment->setSubject('Llama')
|
Chris@18
|
121 ->setOwnerId($this->account->id())
|
Chris@18
|
122 ->setPublished()
|
Chris@18
|
123 ->setCreatedTime(123456789)
|
Chris@18
|
124 ->setChangedTime(123456789);
|
Chris@18
|
125 $comment->save();
|
Chris@18
|
126
|
Chris@18
|
127 return $comment;
|
Chris@18
|
128 }
|
Chris@18
|
129
|
Chris@18
|
130 /**
|
Chris@18
|
131 * {@inheritdoc}
|
Chris@18
|
132 */
|
Chris@18
|
133 protected function getExpectedDocument() {
|
Chris@18
|
134 $self_url = Url::fromUri('base:/jsonapi/comment/comment/' . $this->entity->uuid())->setAbsolute()->toString(TRUE)->getGeneratedUrl();
|
Chris@18
|
135 $author = User::load($this->entity->getOwnerId());
|
Chris@18
|
136 return [
|
Chris@18
|
137 'jsonapi' => [
|
Chris@18
|
138 'meta' => [
|
Chris@18
|
139 'links' => [
|
Chris@18
|
140 'self' => ['href' => 'http://jsonapi.org/format/1.0/'],
|
Chris@18
|
141 ],
|
Chris@18
|
142 ],
|
Chris@18
|
143 'version' => '1.0',
|
Chris@18
|
144 ],
|
Chris@18
|
145 'links' => [
|
Chris@18
|
146 'self' => ['href' => $self_url],
|
Chris@18
|
147 ],
|
Chris@18
|
148 'data' => [
|
Chris@18
|
149 'id' => $this->entity->uuid(),
|
Chris@18
|
150 'type' => 'comment--comment',
|
Chris@18
|
151 'links' => [
|
Chris@18
|
152 'self' => ['href' => $self_url],
|
Chris@18
|
153 ],
|
Chris@18
|
154 'attributes' => [
|
Chris@18
|
155 'created' => '1973-11-29T21:33:09+00:00',
|
Chris@18
|
156 'changed' => (new \DateTime())->setTimestamp($this->entity->getChangedTime())->setTimezone(new \DateTimeZone('UTC'))->format(\DateTime::RFC3339),
|
Chris@18
|
157 'comment_body' => [
|
Chris@18
|
158 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
|
Chris@18
|
159 'format' => 'plain_text',
|
Chris@18
|
160 'processed' => "<p>The name "llama" was adopted by European settlers from native Peruvians.</p>\n",
|
Chris@18
|
161 ],
|
Chris@18
|
162 'default_langcode' => TRUE,
|
Chris@18
|
163 'entity_type' => 'entity_test',
|
Chris@18
|
164 'field_name' => 'comment',
|
Chris@18
|
165 'homepage' => NULL,
|
Chris@18
|
166 'langcode' => 'en',
|
Chris@18
|
167 'name' => NULL,
|
Chris@18
|
168 'status' => TRUE,
|
Chris@18
|
169 'subject' => 'Llama',
|
Chris@18
|
170 'thread' => '01/',
|
Chris@18
|
171 'drupal_internal__cid' => 1,
|
Chris@18
|
172 ],
|
Chris@18
|
173 'relationships' => [
|
Chris@18
|
174 'uid' => [
|
Chris@18
|
175 'data' => [
|
Chris@18
|
176 'id' => $author->uuid(),
|
Chris@18
|
177 'type' => 'user--user',
|
Chris@18
|
178 ],
|
Chris@18
|
179 'links' => [
|
Chris@18
|
180 'related' => ['href' => $self_url . '/uid'],
|
Chris@18
|
181 'self' => ['href' => $self_url . '/relationships/uid'],
|
Chris@18
|
182 ],
|
Chris@18
|
183 ],
|
Chris@18
|
184 'comment_type' => [
|
Chris@18
|
185 'data' => [
|
Chris@18
|
186 'id' => CommentType::load('comment')->uuid(),
|
Chris@18
|
187 'type' => 'comment_type--comment_type',
|
Chris@18
|
188 ],
|
Chris@18
|
189 'links' => [
|
Chris@18
|
190 'related' => ['href' => $self_url . '/comment_type'],
|
Chris@18
|
191 'self' => ['href' => $self_url . '/relationships/comment_type'],
|
Chris@18
|
192 ],
|
Chris@18
|
193 ],
|
Chris@18
|
194 'entity_id' => [
|
Chris@18
|
195 'data' => [
|
Chris@18
|
196 'id' => EntityTest::load(1)->uuid(),
|
Chris@18
|
197 'type' => 'entity_test--bar',
|
Chris@18
|
198 ],
|
Chris@18
|
199 'links' => [
|
Chris@18
|
200 'related' => ['href' => $self_url . '/entity_id'],
|
Chris@18
|
201 'self' => ['href' => $self_url . '/relationships/entity_id'],
|
Chris@18
|
202 ],
|
Chris@18
|
203 ],
|
Chris@18
|
204 'pid' => [
|
Chris@18
|
205 'data' => NULL,
|
Chris@18
|
206 'links' => [
|
Chris@18
|
207 'related' => ['href' => $self_url . '/pid'],
|
Chris@18
|
208 'self' => ['href' => $self_url . '/relationships/pid'],
|
Chris@18
|
209 ],
|
Chris@18
|
210 ],
|
Chris@18
|
211 ],
|
Chris@18
|
212 ],
|
Chris@18
|
213 ];
|
Chris@18
|
214 }
|
Chris@18
|
215
|
Chris@18
|
216 /**
|
Chris@18
|
217 * {@inheritdoc}
|
Chris@18
|
218 */
|
Chris@18
|
219 protected function getPostDocument() {
|
Chris@18
|
220 return [
|
Chris@18
|
221 'data' => [
|
Chris@18
|
222 'type' => 'comment--comment',
|
Chris@18
|
223 'attributes' => [
|
Chris@18
|
224 'entity_type' => 'entity_test',
|
Chris@18
|
225 'field_name' => 'comment',
|
Chris@18
|
226 'subject' => 'Dramallama',
|
Chris@18
|
227 'comment_body' => [
|
Chris@18
|
228 'value' => 'Llamas are awesome.',
|
Chris@18
|
229 'format' => 'plain_text',
|
Chris@18
|
230 ],
|
Chris@18
|
231 ],
|
Chris@18
|
232 'relationships' => [
|
Chris@18
|
233 'entity_id' => [
|
Chris@18
|
234 'data' => [
|
Chris@18
|
235 'type' => 'entity_test--bar',
|
Chris@18
|
236 'id' => EntityTest::load(1)->uuid(),
|
Chris@18
|
237 ],
|
Chris@18
|
238 ],
|
Chris@18
|
239 ],
|
Chris@18
|
240 ],
|
Chris@18
|
241 ];
|
Chris@18
|
242 }
|
Chris@18
|
243
|
Chris@18
|
244 /**
|
Chris@18
|
245 * {@inheritdoc}
|
Chris@18
|
246 */
|
Chris@18
|
247 protected function getExpectedCacheTags(array $sparse_fieldset = NULL) {
|
Chris@18
|
248 $tags = parent::getExpectedCacheTags($sparse_fieldset);
|
Chris@18
|
249 if ($sparse_fieldset === NULL || in_array('comment_body', $sparse_fieldset)) {
|
Chris@18
|
250 $tags = Cache::mergeTags($tags, ['config:filter.format.plain_text']);
|
Chris@18
|
251 }
|
Chris@18
|
252 return $tags;
|
Chris@18
|
253 }
|
Chris@18
|
254
|
Chris@18
|
255 /**
|
Chris@18
|
256 * {@inheritdoc}
|
Chris@18
|
257 */
|
Chris@18
|
258 protected function getExpectedCacheContexts(array $sparse_fieldset = NULL) {
|
Chris@18
|
259 $contexts = parent::getExpectedCacheContexts($sparse_fieldset);
|
Chris@18
|
260 if ($sparse_fieldset === NULL || in_array('comment_body', $sparse_fieldset)) {
|
Chris@18
|
261 $contexts = Cache::mergeContexts($contexts, ['languages:language_interface', 'theme']);
|
Chris@18
|
262 }
|
Chris@18
|
263 return $contexts;
|
Chris@18
|
264 }
|
Chris@18
|
265
|
Chris@18
|
266 /**
|
Chris@18
|
267 * {@inheritdoc}
|
Chris@18
|
268 */
|
Chris@18
|
269 protected function getExpectedUnauthorizedAccessMessage($method) {
|
Chris@18
|
270 switch ($method) {
|
Chris@18
|
271 case 'GET';
|
Chris@18
|
272 return "The 'access comments' permission is required and the comment must be published.";
|
Chris@18
|
273
|
Chris@18
|
274 case 'POST';
|
Chris@18
|
275 return "The 'post comments' permission is required.";
|
Chris@18
|
276
|
Chris@18
|
277 case 'PATCH':
|
Chris@18
|
278 return "The 'edit own comments' permission is required, the user must be the comment author, and the comment must be published.";
|
Chris@18
|
279
|
Chris@18
|
280 default:
|
Chris@18
|
281 return parent::getExpectedUnauthorizedAccessMessage($method);
|
Chris@18
|
282 }
|
Chris@18
|
283 }
|
Chris@18
|
284
|
Chris@18
|
285 /**
|
Chris@18
|
286 * Tests POSTing a comment without critical base fields.
|
Chris@18
|
287 *
|
Chris@18
|
288 * Note that testPostIndividual() is testing with the most minimal
|
Chris@18
|
289 * normalization possible: the one returned by ::getNormalizedPostEntity().
|
Chris@18
|
290 *
|
Chris@18
|
291 * But Comment entities have some very special edge cases:
|
Chris@18
|
292 * - base fields that are not marked as required in
|
Chris@18
|
293 * \Drupal\comment\Entity\Comment::baseFieldDefinitions() yet in fact are
|
Chris@18
|
294 * required.
|
Chris@18
|
295 * - base fields that are marked as required, but yet can still result in
|
Chris@18
|
296 * validation errors other than "missing required field".
|
Chris@18
|
297 */
|
Chris@18
|
298 public function testPostIndividualDxWithoutCriticalBaseFields() {
|
Chris@18
|
299 $this->setUpAuthorization('POST');
|
Chris@18
|
300 $this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE);
|
Chris@18
|
301
|
Chris@18
|
302 $url = Url::fromRoute(sprintf('jsonapi.%s.collection.post', static::$resourceTypeName));
|
Chris@18
|
303 $request_options = [];
|
Chris@18
|
304 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
|
Chris@18
|
305 $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json';
|
Chris@18
|
306 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions());
|
Chris@18
|
307
|
Chris@18
|
308 $remove_field = function (array $normalization, $type, $attribute_name) {
|
Chris@18
|
309 unset($normalization['data'][$type][$attribute_name]);
|
Chris@18
|
310 return $normalization;
|
Chris@18
|
311 };
|
Chris@18
|
312
|
Chris@18
|
313 // DX: 422 when missing 'entity_type' field.
|
Chris@18
|
314 $request_options[RequestOptions::BODY] = Json::encode($remove_field($this->getPostDocument(), 'attributes', 'entity_type'));
|
Chris@18
|
315 $response = $this->request('POST', $url, $request_options);
|
Chris@18
|
316 $this->assertResourceErrorResponse(422, 'entity_type: This value should not be null.', NULL, $response, '/data/attributes/entity_type');
|
Chris@18
|
317
|
Chris@18
|
318 // DX: 422 when missing 'entity_id' field.
|
Chris@18
|
319 $request_options[RequestOptions::BODY] = Json::encode($remove_field($this->getPostDocument(), 'relationships', 'entity_id'));
|
Chris@18
|
320 // @todo Remove the try/catch in https://www.drupal.org/node/2820364.
|
Chris@18
|
321 try {
|
Chris@18
|
322 $response = $this->request('POST', $url, $request_options);
|
Chris@18
|
323 $this->assertResourceErrorResponse(422, 'entity_id: This value should not be null.', NULL, $response, '/data/attributes/entity_id');
|
Chris@18
|
324 }
|
Chris@18
|
325 catch (\Exception $e) {
|
Chris@18
|
326 if (version_compare(phpversion(), '7.0') >= 0) {
|
Chris@18
|
327 $this->assertSame("Error: Call to a member function get() on null\nDrupal\\comment\\Plugin\\Validation\\Constraint\\CommentNameConstraintValidator->getAnonymousContactDetailsSetting()() (Line: 96)\n", $e->getMessage());
|
Chris@18
|
328 }
|
Chris@18
|
329 else {
|
Chris@18
|
330 $this->assertSame(500, $response->getStatusCode());
|
Chris@18
|
331 }
|
Chris@18
|
332 }
|
Chris@18
|
333
|
Chris@18
|
334 // DX: 422 when missing 'field_name' field.
|
Chris@18
|
335 $request_options[RequestOptions::BODY] = Json::encode($remove_field($this->getPostDocument(), 'attributes', 'field_name'));
|
Chris@18
|
336 $response = $this->request('POST', $url, $request_options);
|
Chris@18
|
337 $this->assertResourceErrorResponse(422, 'field_name: This value should not be null.', NULL, $response, '/data/attributes/field_name');
|
Chris@18
|
338 }
|
Chris@18
|
339
|
Chris@18
|
340 /**
|
Chris@18
|
341 * Tests POSTing a comment with and without 'skip comment approval'.
|
Chris@18
|
342 */
|
Chris@18
|
343 public function testPostIndividualSkipCommentApproval() {
|
Chris@18
|
344 $this->setUpAuthorization('POST');
|
Chris@18
|
345 $this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE);
|
Chris@18
|
346
|
Chris@18
|
347 // Create request.
|
Chris@18
|
348 $request_options = [];
|
Chris@18
|
349 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
|
Chris@18
|
350 $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json';
|
Chris@18
|
351 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions());
|
Chris@18
|
352 $request_options[RequestOptions::BODY] = Json::encode($this->getPostDocument());
|
Chris@18
|
353
|
Chris@18
|
354 $url = Url::fromRoute('jsonapi.comment--comment.collection.post');
|
Chris@18
|
355
|
Chris@18
|
356 // Status should be FALSE when posting as anonymous.
|
Chris@18
|
357 $response = $this->request('POST', $url, $request_options);
|
Chris@18
|
358 $this->assertResourceResponse(201, FALSE, $response);
|
Chris@18
|
359 $this->assertFalse(Json::decode((string) $response->getBody())['data']['attributes']['status']);
|
Chris@18
|
360 $this->assertFalse($this->entityStorage->loadUnchanged(2)->isPublished());
|
Chris@18
|
361
|
Chris@18
|
362 // Grant anonymous permission to skip comment approval.
|
Chris@18
|
363 $this->grantPermissionsToTestedRole(['skip comment approval']);
|
Chris@18
|
364
|
Chris@18
|
365 // Status must be TRUE when posting as anonymous and skip comment approval.
|
Chris@18
|
366 $response = $this->request('POST', $url, $request_options);
|
Chris@18
|
367 $this->assertResourceResponse(201, FALSE, $response);
|
Chris@18
|
368 $this->assertTrue(Json::decode((string) $response->getBody())['data']['attributes']['status']);
|
Chris@18
|
369 $this->assertTrue($this->entityStorage->loadUnchanged(3)->isPublished());
|
Chris@18
|
370 }
|
Chris@18
|
371
|
Chris@18
|
372 /**
|
Chris@18
|
373 * {@inheritdoc}
|
Chris@18
|
374 */
|
Chris@18
|
375 protected function getExpectedUnauthorizedAccessCacheability() {
|
Chris@18
|
376 // @see \Drupal\comment\CommentAccessControlHandler::checkAccess()
|
Chris@18
|
377 return parent::getExpectedUnauthorizedAccessCacheability()
|
Chris@18
|
378 ->addCacheTags(['comment:1']);
|
Chris@18
|
379 }
|
Chris@18
|
380
|
Chris@18
|
381 /**
|
Chris@18
|
382 * {@inheritdoc}
|
Chris@18
|
383 */
|
Chris@18
|
384 protected static function entityAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
Chris@18
|
385 // Also reset the 'entity_test' entity access control handler because
|
Chris@18
|
386 // comment access also depends on access to the commented entity type.
|
Chris@18
|
387 \Drupal::entityTypeManager()->getAccessControlHandler('entity_test')->resetCache();
|
Chris@18
|
388 return parent::entityAccess($entity, $operation, $account);
|
Chris@18
|
389 }
|
Chris@18
|
390
|
Chris@18
|
391 /**
|
Chris@18
|
392 * {@inheritdoc}
|
Chris@18
|
393 */
|
Chris@18
|
394 public function testRelated() {
|
Chris@18
|
395 $this->markTestSkipped('Remove this in https://www.drupal.org/project/jsonapi/issues/2940339');
|
Chris@18
|
396 }
|
Chris@18
|
397
|
Chris@18
|
398 /**
|
Chris@18
|
399 * {@inheritdoc}
|
Chris@18
|
400 */
|
Chris@18
|
401 protected static function getIncludePermissions() {
|
Chris@18
|
402 return [
|
Chris@18
|
403 'type' => ['administer comment types'],
|
Chris@18
|
404 'uid' => ['access user profiles'],
|
Chris@18
|
405 ];
|
Chris@18
|
406 }
|
Chris@18
|
407
|
Chris@18
|
408 /**
|
Chris@18
|
409 * {@inheritdoc}
|
Chris@18
|
410 */
|
Chris@18
|
411 public function testCollectionFilterAccess() {
|
Chris@18
|
412 // Verify the expected behavior in the common case.
|
Chris@18
|
413 $this->doTestCollectionFilterAccessForPublishableEntities('subject', 'access comments', 'administer comments');
|
Chris@18
|
414
|
Chris@18
|
415 $collection_url = Url::fromRoute('jsonapi.entity_test--bar.collection');
|
Chris@18
|
416 $request_options = [];
|
Chris@18
|
417 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
|
Chris@18
|
418 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions());
|
Chris@18
|
419
|
Chris@18
|
420 // Go back to a simpler scenario: revoke the admin permission, publish the
|
Chris@18
|
421 // comment and uninstall the query access test module.
|
Chris@18
|
422 $this->revokePermissionsFromTestedRole(['administer comments']);
|
Chris@18
|
423 $this->entity->setPublished()->save();
|
Chris@18
|
424 $this->assertTrue($this->container->get('module_installer')->uninstall(['jsonapi_test_field_filter_access'], TRUE), 'Uninstalled modules.');
|
Chris@18
|
425 // ?filter[spotlight.LABEL]: 1 result. Just as already tested above in
|
Chris@18
|
426 // ::doTestCollectionFilterAccessForPublishableEntities().
|
Chris@18
|
427 $collection_filter_url = $collection_url->setOption('query', ["filter[spotlight.subject]" => $this->entity->label()]);
|
Chris@18
|
428 $response = $this->request('GET', $collection_filter_url, $request_options);
|
Chris@18
|
429 $doc = Json::decode((string) $response->getBody());
|
Chris@18
|
430 $this->assertCount(1, $doc['data']);
|
Chris@18
|
431 // Mark the commented entity as inaccessible.
|
Chris@18
|
432 \Drupal::state()->set('jsonapi__entity_test_filter_access_blacklist', [$this->entity->getCommentedEntityId()]);
|
Chris@18
|
433 Cache::invalidateTags(['state:jsonapi__entity_test_filter_access_blacklist']);
|
Chris@18
|
434 // ?filter[spotlight.LABEL]: 0 results.
|
Chris@18
|
435 $response = $this->request('GET', $collection_filter_url, $request_options);
|
Chris@18
|
436 $doc = Json::decode((string) $response->getBody());
|
Chris@18
|
437 $this->assertCount(0, $doc['data']);
|
Chris@18
|
438 }
|
Chris@18
|
439
|
Chris@18
|
440 /**
|
Chris@18
|
441 * {@inheritdoc}
|
Chris@18
|
442 */
|
Chris@18
|
443 protected static function getExpectedCollectionCacheability(AccountInterface $account, array $collection, array $sparse_fieldset = NULL, $filtered = FALSE) {
|
Chris@18
|
444 $cacheability = parent::getExpectedCollectionCacheability($account, $collection, $sparse_fieldset, $filtered);
|
Chris@18
|
445 if ($filtered) {
|
Chris@18
|
446 $cacheability->addCacheTags(['state:jsonapi__entity_test_filter_access_blacklist']);
|
Chris@18
|
447 }
|
Chris@18
|
448 return $cacheability;
|
Chris@18
|
449 }
|
Chris@18
|
450
|
Chris@18
|
451 /**
|
Chris@18
|
452 * {@inheritdoc}
|
Chris@18
|
453 */
|
Chris@18
|
454 public function testPatchIndividual() {
|
Chris@18
|
455 // Ensure ::getModifiedEntityForPatchTesting() can pick an alternative value
|
Chris@18
|
456 // for the 'entity_id' field.
|
Chris@18
|
457 EntityTest::create([
|
Chris@18
|
458 'name' => $this->randomString(),
|
Chris@18
|
459 'type' => 'bar',
|
Chris@18
|
460 ])->save();
|
Chris@18
|
461
|
Chris@18
|
462 return parent::testPatchIndividual();
|
Chris@18
|
463 }
|
Chris@18
|
464
|
Chris@18
|
465 }
|