CommentNonNodeTest.php 19.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
<?php

/**
 * @file
 * Contains \Drupal\comment\Tests\CommentNonNodeTest.
 */

namespace Drupal\comment\Tests;

use Drupal\comment\CommentInterface;
11
use Drupal\comment\Entity\Comment;
12
use Drupal\comment\Entity\CommentType;
13
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
14
use Drupal\field\Entity\FieldConfig;
15
use Drupal\field\Entity\FieldStorageConfig;
16
use Drupal\field_ui\Tests\FieldUiTestTrait;
17
18
use Drupal\simpletest\WebTestBase;
use Drupal\Core\Entity\EntityInterface;
19
use Drupal\user\RoleInterface;
20
21

/**
22
23
24
 * Tests commenting on a test entity.
 *
 * @group comment
25
26
27
 */
class CommentNonNodeTest extends WebTestBase {

28
  use FieldUiTestTrait;
29
  use CommentTestTrait;
30

31
  public static $modules = array('comment', 'user', 'field_ui', 'entity_test', 'block');
32
33
34
35
36
37

  /**
   * An administrative user with permission to configure comment settings.
   *
   * @var \Drupal\user\UserInterface
   */
38
  protected $adminUser;
39

40
41
42
43
44
45
46
  /**
   * The entity to use within tests.
   *
   * @var \Drupal\entity_test\Entity\EntityTest
   */
  protected $entity;

47
48
49
  /**
   * {@inheritdoc}
   */
50
  protected function setUp() {
51
    parent::setUp();
52
    $this->drupalPlaceBlock('system_breadcrumb_block');
53
    $this->drupalPlaceBlock('page_title_block');
54

55
56
    // Create a bundle for entity_test.
    entity_test_create_bundle('entity_test', 'Entity Test', 'entity_test');
57
58
59
60
61
62
    entity_create('comment_type', array(
      'id' => 'comment',
      'label' => 'Comment settings',
      'description' => 'Comment settings',
      'target_entity_type_id' => 'entity_test',
    ))->save();
63
    // Create comment field on entity_test bundle.
64
    $this->addDefaultCommentField('entity_test', 'entity_test');
65

66
67
    // Verify that bundles are defined correctly.
    $bundles = \Drupal::entityManager()->getBundleInfo('comment');
68
    $this->assertEqual($bundles['comment']['label'], 'Comment settings');
69

70
    // Create test user.
71
    $this->adminUser = $this->drupalCreateUser(array(
72
73
74
75
76
77
78
79
80
      'administer comments',
      'skip comment approval',
      'post comments',
      'access comments',
      'view test entity',
      'administer entity_test content',
    ));

    // Enable anonymous and authenticated user comments.
81
    user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, array(
82
83
84
85
      'access comments',
      'post comments',
      'skip comment approval',
    ));
86
    user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, array(
87
88
89
90
91
92
      'access comments',
      'post comments',
      'skip comment approval',
    ));

    // Create a test entity.
93
    $random_label = $this->randomMachineName();
94
95
    $data = array('type' => 'entity_test', 'name' => $random_label);
    $this->entity = entity_create('entity_test', $data);
96
97
98
99
100
101
102
103
    $this->entity->save();
  }

  /**
   * Posts a comment.
   *
   * @param \Drupal\Core\Entity\EntityInterface|null $entity
   *   Entity to post comment on or NULL to post to the previously loaded page.
104
   * @param string $comment
105
   *   Comment body.
106
   * @param string $subject
107
   *   Comment subject.
108
   * @param mixed $contact
109
110
   *   Set to NULL for no contact info, TRUE to ignore success checking, and
   *   array of values to set contact info.
111
112
113
   *
   * @return \Drupal\comment\CommentInterface
   *   The new comment entity.
114
115
116
117
118
   */
  function postComment(EntityInterface $entity, $comment, $subject = '', $contact = NULL) {
    $edit = array();
    $edit['comment_body[0][value]'] = $comment;

119
120
    $field = FieldConfig::loadByName('entity_test', 'entity_test', 'comment');
    $preview_mode = $field->getSetting('preview');
121
122
123

    // Must get the page before we test for fields.
    if ($entity !== NULL) {
124
      $this->drupalGet('comment/reply/entity_test/' . $entity->id() . '/comment');
125
126
    }

127
128
129
130
    // Determine the visibility of subject form field.
    if (entity_get_form_display('comment', 'comment', 'default')->getComponent('subject')) {
      // Subject input allowed.
      $edit['subject[0][value]'] = $subject;
131
132
    }
    else {
133
      $this->assertNoFieldByName('subject[0][value]', '', 'Subject field not found.');
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    }

    if ($contact !== NULL && is_array($contact)) {
      $edit += $contact;
    }
    switch ($preview_mode) {
      case DRUPAL_REQUIRED:
        // Preview required so no save button should be found.
        $this->assertNoFieldByName('op', t('Save'), 'Save button not found.');
        $this->drupalPostForm(NULL, $edit, t('Preview'));
        // Don't break here so that we can test post-preview field presence and
        // function below.
      case DRUPAL_OPTIONAL:
        $this->assertFieldByName('op', t('Preview'), 'Preview button found.');
        $this->assertFieldByName('op', t('Save'), 'Save button found.');
        $this->drupalPostForm(NULL, $edit, t('Save'));
        break;

      case DRUPAL_DISABLED:
        $this->assertNoFieldByName('op', t('Preview'), 'Preview button not found.');
        $this->assertFieldByName('op', t('Save'), 'Save button found.');
        $this->drupalPostForm(NULL, $edit, t('Save'));
        break;
    }
    $match = array();
    // Get comment ID
    preg_match('/#comment-([0-9]+)/', $this->getURL(), $match);

    // Get comment.
    if ($contact !== TRUE) { // If true then attempting to find error message.
      if ($subject) {
        $this->assertText($subject, 'Comment subject posted.');
      }
      $this->assertText($comment, 'Comment body posted.');
      $this->assertTrue((!empty($match) && !empty($match[1])), 'Comment ID found.');
    }

    if (isset($match[1])) {
172
      return Comment::load($match[1]);
173
174
175
176
177
178
179
180
    }
  }

  /**
   * Checks current page for specified comment.
   *
   * @param \Drupal\comment\CommentInterface $comment
   *   The comment object.
181
   * @param bool $reply
182
183
   *   Boolean indicating whether the comment is a reply to another comment.
   *
184
   * @return bool
185
186
187
188
189
   *   Boolean indicating whether the comment was found.
   */
  function commentExists(CommentInterface $comment = NULL, $reply = FALSE) {
    if ($comment) {
      $regex = '/' . ($reply ? '<div class="indented">(.*?)' : '');
190
191
192
      $regex .= '<a id="comment-' . $comment->id() . '"(.*?)';
      $regex .= $comment->getSubject() . '(.*?)';
      $regex .= $comment->comment_body->value . '(.*?)';
193
194
      $regex .= '/s';

195
      return (boolean) preg_match($regex, $this->getRawContent());
196
197
198
199
200
201
202
203
204
    }
    else {
      return FALSE;
    }
  }

  /**
   * Checks whether the commenter's contact information is displayed.
   *
205
   * @return bool
206
207
208
   *   Contact info is available.
   */
  function commentContactInfoAvailable() {
209
    return preg_match('/(input).*?(name="name").*?(input).*?(name="mail").*?(input).*?(name="homepage")/s', $this->getRawContent());
210
211
212
213
214
215
216
217
218
  }

  /**
   * Performs the specified operation on the specified comment.
   *
   * @param object $comment
   *   Comment to perform operation on.
   * @param string $operation
   *   Operation to perform.
219
   * @param bool $approval
220
221
222
223
224
225
226
227
228
229
   *   Operation is found on approval page.
   */
  function performCommentOperation($comment, $operation, $approval = FALSE) {
    $edit = array();
    $edit['operation'] = $operation;
    $edit['comments[' . $comment->id() . ']'] = TRUE;
    $this->drupalPostForm('admin/content/comment' . ($approval ? '/approval' : ''), $edit, t('Update'));

    if ($operation == 'delete') {
      $this->drupalPostForm(NULL, array(), t('Delete comments'));
230
      $this->assertRaw(\Drupal::translation()->formatPlural(1, 'Deleted 1 comment.', 'Deleted @count comments.'), format_string('Operation "@operation" was performed on comment.', array('@operation' => $operation)));
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
    }
    else {
      $this->assertText(t('The update has been performed.'), format_string('Operation "@operation" was performed on comment.', array('@operation' => $operation)));
    }
  }

  /**
   * Gets the comment ID for an unapproved comment.
   *
   * @param string $subject
   *   Comment subject to find.
   *
   * @return integer
   *   Comment ID.
   */
  function getUnapprovedComment($subject) {
    $this->drupalGet('admin/content/comment/approval');
248
    preg_match('/href="(.*?)#comment-([^"]+)"(.*?)>(' . $subject . ')/', $this->getRawContent(), $match);
249
250
251
252
253
254
255
256
257

    return $match[2];
  }

  /**
   * Tests anonymous comment functionality.
   */
  function testCommentFunctionality() {
    $limited_user = $this->drupalCreateUser(array(
258
      'administer entity_test fields'
259
260
261
    ));
    $this->drupalLogin($limited_user);
    // Test that default field exists.
262
    $this->drupalGet('entity_test/structure/entity_test/fields');
263
    $this->assertText(t('Comments'));
264
    $this->assertLinkByHref('entity_test/structure/entity_test/fields/entity_test.entity_test.comment');
265
    // Test widget hidden option is not visible when there's no comments.
266
267
    $this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.comment');
    $this->assertResponse(200);
268
    $this->assertNoField('edit-default-value-input-comment-und-0-status-0');
269
270
271
    // Test that field to change cardinality is not available.
    $this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.comment/storage');
    $this->assertResponse(200);
272
273
    $this->assertNoField('cardinality_number');
    $this->assertNoField('cardinality');
274

275
    $this->drupalLogin($this->adminUser);
276

277
278
279
280
281
    // Test breadcrumb on comment add page.
    $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment');
    $xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a';
    $this->assertEqual(current($this->xpath($xpath)), $this->entity->label(), 'Last breadcrumb item is equal to node title on comment reply page.');

282
    // Post a comment.
283
    /** @var \Drupal\comment\CommentInterface $comment1 */
284
    $comment1 = $this->postComment($this->entity, $this->randomMachineName(), $this->randomMachineName());
285
286
    $this->assertTrue($this->commentExists($comment1), 'Comment on test entity exists.');

287
288
289
290
291
292
293
294
295
296
297
298
299
300
    // Test breadcrumb on comment reply page.
    $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment/' . $comment1->id());
    $xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a';
    $this->assertEqual(current($this->xpath($xpath)), $comment1->getSubject(), 'Last breadcrumb item is equal to comment title on comment reply page.');

    // Test breadcrumb on comment edit page.
    $this->drupalGet('comment/' . $comment1->id() . '/edit');
    $xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a';
    $this->assertEqual(current($this->xpath($xpath)), $comment1->getSubject(), 'Last breadcrumb item is equal to comment subject on edit page.');

    // Test breadcrumb on comment delete page.
    $this->drupalGet('comment/' . $comment1->id() . '/delete');
    $xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a';
    $this->assertEqual(current($this->xpath($xpath)), $comment1->getSubject(), 'Last breadcrumb item is equal to comment subject on delete confirm page.');
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

    // Unpublish the comment.
    $this->performCommentOperation($comment1, 'unpublish');
    $this->drupalGet('admin/content/comment/approval');
    $this->assertRaw('comments[' . $comment1->id() . ']', 'Comment was unpublished.');

    // Publish the comment.
    $this->performCommentOperation($comment1, 'publish', TRUE);
    $this->drupalGet('admin/content/comment');
    $this->assertRaw('comments[' . $comment1->id() . ']', 'Comment was published.');

    // Delete the comment.
    $this->performCommentOperation($comment1, 'delete');
    $this->drupalGet('admin/content/comment');
    $this->assertNoRaw('comments[' . $comment1->id() . ']', 'Comment was deleted.');

    // Post another comment.
318
    $comment1 = $this->postComment($this->entity, $this->randomMachineName(), $this->randomMachineName());
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    $this->assertTrue($this->commentExists($comment1), 'Comment on test entity exists.');

    // Check that the comment was found.
    $this->drupalGet('admin/content/comment');
    $this->assertRaw('comments[' . $comment1->id() . ']', 'Comment was published.');

    // Check that entity access applies to administrative page.
    $this->assertText($this->entity->label(), 'Name of commented account found.');
    $limited_user = $this->drupalCreateUser(array(
      'administer comments',
    ));
    $this->drupalLogin($limited_user);
    $this->drupalGet('admin/content/comment');
    $this->assertNoText($this->entity->label(), 'No commented account name found.');

    $this->drupalLogout();

    // Deny anonymous users access to comments.
337
    user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array(
338
339
340
341
342
343
344
      'access comments' => FALSE,
      'post comments' => FALSE,
      'skip comment approval' => FALSE,
      'view test entity' => TRUE,
    ));

    // Attempt to view comments while disallowed.
345
    $this->drupalGet('entity-test/' . $this->entity->id());
346
347
348
349
    $this->assertNoPattern('@<h2[^>]*>Comments</h2>@', 'Comments were not displayed.');
    $this->assertNoLink('Add new comment', 'Link to add comment was found.');

    // Attempt to view test entity comment form while disallowed.
350
    $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment');
351
    $this->assertResponse(403);
352
    $this->assertNoFieldByName('subject[0][value]', '', 'Subject field not found.');
353
354
    $this->assertNoFieldByName('comment_body[0][value]', '', 'Comment field not found.');

355
    user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array(
356
357
358
359
360
      'access comments' => TRUE,
      'post comments' => FALSE,
      'view test entity' => TRUE,
      'skip comment approval' => FALSE,
    ));
361
    $this->drupalGet('entity_test/' . $this->entity->id());
362
363
364
    $this->assertPattern('@<h2[^>]*>Comments</h2>@', 'Comments were displayed.');
    $this->assertLink('Log in', 0, 'Link to log in was found.');
    $this->assertLink('register', 0, 'Link to register was found.');
365
    $this->assertNoFieldByName('subject[0][value]', '', 'Subject field not found.');
366
367
368
369
370
    $this->assertNoFieldByName('comment_body[0][value]', '', 'Comment field not found.');

    // Test the combination of anonymous users being able to post, but not view
    // comments, to ensure that access to post comments doesn't grant access to
    // view them.
371
    user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array(
372
373
374
375
376
      'access comments' => FALSE,
      'post comments' => TRUE,
      'skip comment approval' => TRUE,
      'view test entity' => TRUE,
    ));
377
    $this->drupalGet('entity_test/' . $this->entity->id());
378
    $this->assertNoPattern('@<h2[^>]*>Comments</h2>@', 'Comments were not displayed.');
379
    $this->assertFieldByName('subject[0][value]', '', 'Subject field found.');
380
381
    $this->assertFieldByName('comment_body[0][value]', '', 'Comment field found.');

382
    $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment/' . $comment1->id());
383
    $this->assertResponse(403);
384
    $this->assertNoText($comment1->getSubject(), 'Comment not displayed.');
385
386
387

    // Test comment field widget changes.
    $limited_user = $this->drupalCreateUser(array(
388
      'administer entity_test fields',
389
390
391
392
      'view test entity',
      'administer entity_test content',
    ));
    $this->drupalLogin($limited_user);
393
    $this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.comment');
394
395
396
397
    $this->assertNoFieldChecked('edit-default-value-input-comment-0-status-0');
    $this->assertNoFieldChecked('edit-default-value-input-comment-0-status-1');
    $this->assertFieldChecked('edit-default-value-input-comment-0-status-2');
    // Test comment option change in field settings.
398
399
    $edit = array(
      'default_value_input[comment][0][status]' => CommentItemInterface::CLOSED,
400
      'settings[anonymous]' => COMMENT_ANONYMOUS_MAY_CONTACT,
401
    );
402
    $this->drupalPostForm(NULL, $edit, t('Save settings'));
403
    $this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.comment');
404
405
406
    $this->assertNoFieldChecked('edit-default-value-input-comment-0-status-0');
    $this->assertFieldChecked('edit-default-value-input-comment-0-status-1');
    $this->assertNoFieldChecked('edit-default-value-input-comment-0-status-2');
407
    $this->assertFieldByName('settings[anonymous]', COMMENT_ANONYMOUS_MAY_CONTACT);
408

409
410
411
412
413
414
415
416
417
    // Add a new comment-type.
    $bundle = CommentType::create(array(
      'id' => 'foobar',
      'label' => 'Foobar',
      'description' => '',
      'target_entity_type_id' => 'entity_test',
    ));
    $bundle->save();

418
    // Add a new comment field.
419
    $storage_edit = array(
420
      'settings[comment_type]' => 'foobar',
421
422
    );
    $this->fieldUIAddNewField('entity_test/structure/entity_test', 'foobar', 'Foobar', 'comment', $storage_edit);
423

424
    // Add a third comment field.
425
    $this->fieldUIAddNewField('entity_test/structure/entity_test', 'barfoo', 'BarFoo', 'comment', $storage_edit);
426
427

    // Check the field contains the correct comment type.
428
    $field_storage = FieldStorageConfig::load('entity_test.field_barfoo');
429
430
    $this->assertTrue($field_storage);
    $this->assertEqual($field_storage->getSetting('comment_type'), 'foobar');
431
    $this->assertEqual($field_storage->getCardinality(), 1);
432

433
    // Test the new entity commenting inherits default.
434
    $random_label = $this->randomMachineName();
435
436
    $data = array('bundle' => 'entity_test', 'name' => $random_label);
    $new_entity = entity_create('entity_test', $data);
437
    $new_entity->save();
438
    $this->drupalGet('entity_test/manage/' . $new_entity->id() . '/edit');
439
440
441
442
    $this->assertNoFieldChecked('edit-field-foobar-0-status-1');
    $this->assertFieldChecked('edit-field-foobar-0-status-2');
    $this->assertNoField('edit-field-foobar-0-status-0');

443
    // @todo Check proper url and form https://www.drupal.org/node/2458323
444
    $this->drupalGet('comment/reply/entity_test/comment/' . $new_entity->id());
445
    $this->assertNoFieldByName('subject[0][value]', '', 'Subject field found.');
446
    $this->assertNoFieldByName('comment_body[0][value]', '', 'Comment field found.');
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464

    // Test removal of comment_body field.
    $limited_user = $this->drupalCreateUser(array(
      'administer entity_test fields',
      'post comments',
      'administer comment fields',
      'administer comment types',
    ));
    $this->drupalLogin($limited_user);

    $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment');
    $this->assertFieldByName('comment_body[0][value]', '', 'Comment body field found.');
    $this->fieldUIDeleteField('admin/structure/comment/manage/comment', 'comment.comment.comment_body', 'Comment', 'Comment settings');
    $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment');
    $this->assertNoFieldByName('comment_body[0][value]', '', 'Comment body field not found.');
    // Set subject field to autogenerate it.
    $edit = ['subject[0][value]' => ''];
    $this->drupalPostForm(NULL, $edit, t('Save'));
465
466
  }

467
  /**
468
   * Tests comment fields cannot be added to entity types without integer IDs.
469
   */
470
471
  public function testsNonIntegerIdEntities() {
    // Create a bundle for entity_test_string_id.
472
473
474
475
476
    entity_test_create_bundle('entity_test', 'Entity Test', 'entity_test_string_id');
    $limited_user = $this->drupalCreateUser(array(
      'administer entity_test_string_id fields',
    ));
    $this->drupalLogin($limited_user);
477
478
    // Visit the Field UI field add page.
    $this->drupalGet('entity_test_string_id/structure/entity_test/fields/add-field');
479
    // Ensure field isn't shown for string IDs.
480
    $this->assertNoOption('edit-new-storage-type', 'comment');
481
    // Ensure a core field type shown.
482
    $this->assertOption('edit-new-storage-type', 'boolean');
483

484
    // Create a bundle for entity_test_no_id.
485
486
487
488
    entity_test_create_bundle('entity_test', 'Entity Test', 'entity_test_no_id');
    $this->drupalLogin($this->drupalCreateUser(array(
      'administer entity_test_no_id fields',
    )));
489
490
    // Visit the Field UI field add page.
    $this->drupalGet('entity_test_no_id/structure/entity_test/fields/add-field');
491
    // Ensure field isn't shown for empty IDs.
492
    $this->assertNoOption('edit-new-storage-type', 'comment');
493
    // Ensure a core field type shown.
494
    $this->assertOption('edit-new-storage-type', 'boolean');
495
496
  }

497
}