/**
  * Tests the node comment statistics.
  */
 function testCommentNodeCommentStatistics()
 {
     $node_storage = $this->container->get('entity.manager')->getStorage('node');
     // Set comments to have subject and preview disabled.
     $this->drupalLogin($this->adminUser);
     $this->setCommentPreview(DRUPAL_DISABLED);
     $this->setCommentForm(TRUE);
     $this->setCommentSubject(FALSE);
     $this->setCommentSettings('default_mode', CommentManagerInterface::COMMENT_MODE_THREADED, 'Comment paging changed.');
     $this->drupalLogout();
     // Checks the initial values of node comment statistics with no comment.
     $node = $node_storage->load($this->node->id());
     $this->assertEqual($node->get('comment')->last_comment_timestamp, $this->node->getCreatedTime(), 'The initial value of node last_comment_timestamp is the node created date.');
     $this->assertEqual($node->get('comment')->last_comment_name, NULL, 'The initial value of node last_comment_name is NULL.');
     $this->assertEqual($node->get('comment')->last_comment_uid, $this->webUser->id(), 'The initial value of node last_comment_uid is the node uid.');
     $this->assertEqual($node->get('comment')->comment_count, 0, 'The initial value of node comment_count is zero.');
     // Post comment #1 as web_user2.
     $this->drupalLogin($this->webUser2);
     $comment_text = $this->randomMachineName();
     $this->postComment($this->node, $comment_text);
     // Checks the new values of node comment statistics with comment #1.
     // The node cache needs to be reset before reload.
     $node_storage->resetCache(array($this->node->id()));
     $node = $node_storage->load($this->node->id());
     $this->assertEqual($node->get('comment')->last_comment_name, NULL, 'The value of node last_comment_name is NULL.');
     $this->assertEqual($node->get('comment')->last_comment_uid, $this->webUser2->id(), 'The value of node last_comment_uid is the comment #1 uid.');
     $this->assertEqual($node->get('comment')->comment_count, 1, 'The value of node comment_count is 1.');
     // Prepare for anonymous comment submission (comment approval enabled).
     $this->drupalLogin($this->adminUser);
     user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array('access comments' => TRUE, 'post comments' => TRUE, 'skip comment approval' => FALSE));
     // Ensure that the poster can leave some contact info.
     $this->setCommentAnonymous('1');
     $this->drupalLogout();
     // Post comment #2 as anonymous (comment approval enabled).
     $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment');
     $anonymous_comment = $this->postComment($this->node, $this->randomMachineName(), '', TRUE);
     // Checks the new values of node comment statistics with comment #2 and
     // ensure they haven't changed since the comment has not been moderated.
     // The node needs to be reloaded with the cache reset.
     $node_storage->resetCache(array($this->node->id()));
     $node = $node_storage->load($this->node->id());
     $this->assertEqual($node->get('comment')->last_comment_name, NULL, 'The value of node last_comment_name is still NULL.');
     $this->assertEqual($node->get('comment')->last_comment_uid, $this->webUser2->id(), 'The value of node last_comment_uid is still the comment #1 uid.');
     $this->assertEqual($node->get('comment')->comment_count, 1, 'The value of node comment_count is still 1.');
     // Prepare for anonymous comment submission (no approval required).
     $this->drupalLogin($this->adminUser);
     user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array('access comments' => TRUE, 'post comments' => TRUE, 'skip comment approval' => TRUE));
     $this->drupalLogout();
     // Post comment #3 as anonymous.
     $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment');
     $anonymous_comment = $this->postComment($this->node, $this->randomMachineName(), '', array('name' => $this->randomMachineName()));
     $comment_loaded = Comment::load($anonymous_comment->id());
     // Checks the new values of node comment statistics with comment #3.
     // The node needs to be reloaded with the cache reset.
     $node_storage->resetCache(array($this->node->id()));
     $node = $node_storage->load($this->node->id());
     $this->assertEqual($node->get('comment')->last_comment_name, $comment_loaded->getAuthorName(), 'The value of node last_comment_name is the name of the anonymous user.');
     $this->assertEqual($node->get('comment')->last_comment_uid, 0, 'The value of node last_comment_uid is zero.');
     $this->assertEqual($node->get('comment')->comment_count, 2, 'The value of node comment_count is 2.');
 }
 /**
  * Tests the unpublish comment by keyword action.
  */
 function testCommentUnpublishByKeyword()
 {
     $this->drupalLogin($this->adminUser);
     $keyword_1 = $this->randomMachineName();
     $keyword_2 = $this->randomMachineName();
     $action = entity_create('action', array('id' => 'comment_unpublish_by_keyword_action', 'label' => $this->randomMachineName(), 'type' => 'comment', 'configuration' => array('keywords' => array($keyword_1, $keyword_2)), 'plugin' => 'comment_unpublish_by_keyword_action'));
     $action->save();
     $comment = $this->postComment($this->node, $keyword_2, $this->randomMachineName());
     // Load the full comment so that status is available.
     $comment = Comment::load($comment->id());
     $this->assertTrue($comment->isPublished() === TRUE, 'The comment status was set to published.');
     $action->execute(array($comment));
     $this->assertTrue($comment->isPublished() === FALSE, 'The comment status was set to not published.');
 }
 /**
  * Tests that comments are deleted with the node.
  */
 function testNodeDeletion()
 {
     $this->drupalLogin($this->webUser);
     $comment = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName());
     $this->assertTrue($comment->id(), 'The comment could be loaded.');
     $this->node->delete();
     $this->assertFalse(Comment::load($comment->id()), 'The comment could not be loaded after the node was deleted.');
     // Make sure the comment field storage and all its fields are deleted when
     // the node type is deleted.
     $this->assertNotNull(FieldStorageConfig::load('node.comment'), 'Comment field storage exists');
     $this->assertNotNull(FieldConfig::load('node.article.comment'), 'Comment field exists');
     // Delete the node type.
     entity_delete_multiple('node_type', array($this->node->bundle()));
     $this->assertNull(FieldStorageConfig::load('node.comment'), 'Comment field storage deleted');
     $this->assertNull(FieldConfig::load('node.article.comment'), 'Comment field deleted');
 }
 /**
  * Tests that comments are deleted with the node.
  */
 function testNodeDeletion()
 {
     $this->drupalLogin($this->web_user);
     $comment = $this->postComment($this->node, $this->randomName(), $this->randomName());
     $this->assertTrue($comment->id(), 'The comment could be loaded.');
     $this->node->delete();
     $this->assertFalse(Comment::load($comment->id()), 'The comment could not be loaded after the node was deleted.');
     // Make sure the comment field and all its instances are deleted when node
     // type is deleted.
     $this->assertNotNull(entity_load('field_storage_config', 'node.comment'), 'Comment field exists');
     $this->assertNotNull(entity_load('field_instance_config', 'node.article.comment'), 'Comment instance exists');
     // Delete the node type.
     entity_delete_multiple('node_type', array($this->node->bundle()));
     $this->assertNull(entity_load('field_storage_config', 'node.comment'), 'Comment field deleted');
     $this->assertNull(entity_load('field_instance_config', 'node.article.comment'), 'Comment instance deleted');
 }
 public function add($comment, $entity, $oldRevisionId = NULL, $newRevisionId = NULL, $diffFieldName = NULL)
 {
     // If the author of the change recently made another change or comment
     // update that comment instead of making a new comment.
     // This keeps the comments easier to read and reduces notification noise.
     //expect array with keys mandatory keys
     // 'comment_type', 'field_name'
     // and optional keys
     // 'subject', 'comment_body' and 'uid'.
     // We omit to test comment_type is same current and last
     // also will blow up if new fields added
     //Default to current user as author
     if (!isset($comment['uid'])) {
         $comment['uid'] = \Drupal::currentUser()->id();
     }
     // Get last comment; can be null if no previous comments exist.
     // We cannot use the values of the last comment stored on the entity,
     // as these are only updated when the entity is loaded.
     $lastSubject = NULL;
     $lastAuthor = NULL;
     $lastTime = NULL;
     $lastComment = NULL;
     $lastCid = \Drupal::entityQuery('comment')->condition('entity_id', $entity->id())->condition('entity_type', $entity->getEntityTypeId())->sort('cid', 'DESC')->range(0, 1)->execute();
     $lastCid = reset($lastCid);
     // value of first element, or false if none.
     if ($lastCid) {
         $lastComment = Comment::load($lastCid);
         if (!empty($lastComment)) {
             $lastSubject = $lastComment->getSubject();
             $lastAuthor = $lastComment->getOwnerId();
             $lastTime = $lastComment->getChangedTime();
         }
     }
     $this->setDefaultSubjectIfNeeded($comment);
     // Evaluate whether to update last comment or create new one
     $hasLastSameAuthor = $lastAuthor === $comment['uid'];
     $isLastWithinPeriod = TRUE;
     //((REQUEST_TIME - $lastTime) < 30);
     $isLastChangeRecord = $lastSubject === 'Change record';
     $isNewChangeRecord = $comment['subject'] === 'Change record';
     if ($lastComment && $hasLastSameAuthor && $isLastWithinPeriod && ($isLastChangeRecord || $isNewChangeRecord)) {
         $this->updateLast($comment, $oldRevisionId, $newRevisionId, $diffFieldName, $entity, $lastComment);
     } else {
         $this->createNew($comment, $oldRevisionId, $newRevisionId, $diffFieldName, $entity);
     }
 }
 /**
  * Tests migration of comments from Drupal 7.
  */
 public function testCommentMigration()
 {
     $comment = Comment::load(1);
     $this->assertTrue($comment instanceof CommentInterface);
     /** @var \Drupal\comment\CommentInterface $comment */
     $this->assertIdentical('A comment', $comment->getSubject());
     $this->assertIdentical('1421727536', $comment->getCreatedTime());
     $this->assertIdentical('1421727536', $comment->getChangedTime());
     $this->assertTrue($comment->getStatus());
     $this->assertIdentical('admin', $comment->getAuthorName());
     $this->assertIdentical('*****@*****.**', $comment->getAuthorEmail());
     $this->assertIdentical('This is a comment', $comment->comment_body->value);
     $this->assertIdentical('filtered_html', $comment->comment_body->format);
     $node = $comment->getCommentedEntity();
     $this->assertTrue($node instanceof NodeInterface);
     $this->assertIdentical('1', $node->id());
 }
  /**
   * Test patching a comment using both HAL+JSON and JSON.
   */
  public function testUpdateComment() {
    $entity_type = 'comment';
    // Enables the REST service for 'comment' entity type.
    $this->enableService('entity:' . $entity_type, 'PATCH', ['hal_json', 'json']);
    $permissions = $this->entityPermissions($entity_type, 'update');
    $account = $this->drupalCreateUser($permissions);
    $account->set('mail', '*****@*****.**');
    $this->drupalLogin($account);

    // Create & save an entity to comment on, plus a comment.
    $entity_test = EntityTest::create();
    $entity_test->save();
    $entity_values = $this->entityValues($entity_type);
    $entity_values['entity_id'] = $entity_test->id();
    $entity_values['uid'] = $account->id();
    $comment = Comment::create($entity_values);
    $comment->save();

    $this->pass('Test case 1: PATCH comment using HAL+JSON.');
    $comment->setSubject('Initial subject')->save();
    $read_only_fields = [
      'name',
      'created',
      'changed',
      'status',
      'thread',
      'entity_type',
      'field_name',
      'entity_id',
      'uid',
    ];
    $this->assertNotEqual('Updated subject', $comment->getSubject());
    $comment->setSubject('Updated subject');
    $this->patchEntity($comment, $read_only_fields, $account, 'hal_json', 'application/hal+json');
    $comment = Comment::load($comment->id());
    $this->assertEqual('Updated subject', $comment->getSubject());

    $this->pass('Test case 1: PATCH comment using JSON.');
    $comment->setSubject('Initial subject')->save();
    $read_only_fields = [
      'pid', // Extra compared to HAL+JSON.
      'entity_id',
      'uid',
      'name',
      'homepage', // Extra compared to HAL+JSON.
      'created',
      'changed',
      'status',
      'thread',
      'entity_type',
      'field_name',
    ];
    $this->assertNotEqual('Updated subject', $comment->getSubject());
    $comment->setSubject('Updated subject');
    $this->patchEntity($comment, $read_only_fields, $account, 'json', 'application/json');
    $comment = Comment::load($comment->id());
    $this->assertEqual('Updated subject', $comment->getSubject());
  }
 /**
  * Test translating comments.
  */
 function testCommentTranslateTab()
 {
     // Allow auto-accept.
     $default_translator = Translator::load('test_translator');
     $default_translator->setAutoAccept(TRUE)->save();
     // Add default comment type.
     $this->addDefaultCommentField('node', 'article');
     // Enable comment translation.
     /** @var \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager */
     $content_translation_manager = \Drupal::service('content_translation.manager');
     $content_translation_manager->setEnabled('comment', 'comment', TRUE);
     drupal_static_reset();
     \Drupal::entityManager()->clearCachedDefinitions();
     \Drupal::service('router.builder')->rebuild();
     \Drupal::service('entity.definition_update_manager')->applyUpdates();
     $this->applySchemaUpdates();
     // Change comment_body field to be translatable.
     $comment_body = FieldConfig::loadByName('comment', 'comment', 'comment_body');
     $comment_body->setTranslatable(TRUE)->save();
     // Create a user that is allowed to translate comments.
     $permissions = array_merge($this->translator_permissions, array('translate comment', 'post comments', 'skip comment approval', 'edit own comments', 'access comments'));
     $this->loginAsTranslator($permissions, TRUE);
     // Create an english source article.
     $node = $this->createTranslatableNode('article', 'en');
     // Add a comment.
     $this->drupalGet('node/' . $node->id());
     $edit = array('subject[0][value]' => $this->randomMachineName(), 'comment_body[0][value]' => $this->randomMachineName());
     $this->drupalPostForm(NULL, $edit, t('Save'));
     $this->assertText(t('Your comment has been posted.'));
     // Go to the translate tab.
     $this->clickLink('Edit');
     $this->assertTrue(preg_match('|comment/(\\d+)/edit$|', $this->getUrl(), $matches), 'Comment found');
     $comment = Comment::load($matches[1]);
     $this->clickLink('Translate');
     // Assert some basic strings on that page.
     $this->assertText(t('Translations of @title', array('@title' => $comment->getSubject())));
     $this->assertText(t('Pending Translations'));
     // Request translations.
     $edit = array('languages[de]' => TRUE, 'languages[es]' => TRUE);
     $this->drupalPostForm(NULL, $edit, t('Request translation'));
     // Verify that we are on the translate tab.
     $this->assertText(t('2 jobs need to be checked out.'));
     // Submit all jobs.
     $this->assertText($comment->getSubject());
     $this->drupalPostForm(NULL, array(), t('Submit to provider and continue'));
     $this->assertText($comment->getSubject());
     $this->drupalPostForm(NULL, array(), t('Submit to provider'));
     // Make sure that we're back on the translate tab.
     $this->assertUrl($comment->url('canonical', array('absolute' => TRUE)) . '/translations');
     $this->assertText(t('Test translation created.'));
     $this->assertNoText(t('The translation of @title to @language is finished and can now be reviewed.', array('@title' => $comment->getSubject(), '@language' => t('Spanish'))));
     $this->assertText(t('The translation for @title has been accepted as es: @target.', array('@title' => $comment->getSubject(), '@target' => $comment->getSubject())));
     // The translated content should be in place.
     $this->clickLink('de(de-ch): ' . $comment->getSubject());
     $this->assertText('de(de-ch): ' . $comment->get('comment_body')->value);
     $this->drupalGet('comment/1/translations');
     $this->clickLink('es: ' . $comment->getSubject());
     $this->drupalGet('es/node/' . $comment->id());
     $this->assertText('es: ' . $comment->get('comment_body')->value);
 }
 /**
  * Posts a comment.
  *
  * @param \Drupal\Core\Entity\EntityInterface|null $entity
  *   Node to post comment on or NULL to post to the previously loaded page.
  * @param string $comment
  *   Comment body.
  * @param string $subject
  *   Comment subject.
  * @param string $contact
  *   Set to NULL for no contact info, TRUE to ignore success checking, and
  *   array of values to set contact info.
  * @param string $field_name
  *   (optional) Field name through which the comment should be posted.
  *   Defaults to 'comment'.
  *
  * @return \Drupal\comment\CommentInterface|null
  *   The posted comment or NULL when posted comment was not found.
  */
 public function postComment($entity, $comment, $subject = '', $contact = NULL, $field_name = 'comment')
 {
     $edit = array();
     $edit['comment_body[0][value]'] = $comment;
     if ($entity !== NULL) {
         $field = FieldConfig::loadByName('node', $entity->bundle(), $field_name);
     } else {
         $field = FieldConfig::loadByName('node', 'article', $field_name);
     }
     $preview_mode = $field->getSetting('preview');
     // Must get the page before we test for fields.
     if ($entity !== NULL) {
         $this->drupalGet('comment/reply/node/' . $entity->id() . '/' . $field_name);
     }
     // 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;
     } else {
         $this->assertNoFieldByName('subject[0][value]', '', 'Subject field not found.');
     }
     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.
         // 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])) {
         \Drupal::entityManager()->getStorage('comment')->resetCache(array($match[1]));
         return Comment::load($match[1]);
     }
 }
Exemple #10
0
 /**
  * Delete account and remove all content.
  */
 function testUserDelete()
 {
     $node_storage = $this->container->get('entity.manager')->getStorage('node');
     $this->config('user.settings')->set('cancel_method', 'user_cancel_delete')->save();
     \Drupal::service('module_installer')->install(array('comment'));
     $this->resetAll();
     $this->addDefaultCommentField('node', 'page');
     $user_storage = $this->container->get('entity.manager')->getStorage('user');
     // Create a user.
     $account = $this->drupalCreateUser(array('cancel account', 'post comments', 'skip comment approval'));
     $this->drupalLogin($account);
     // Load a real user object.
     $user_storage->resetCache(array($account->id()));
     $account = $user_storage->load($account->id());
     // Create a simple node.
     $node = $this->drupalCreateNode(array('uid' => $account->id()));
     // Create comment.
     $edit = array();
     $edit['subject[0][value]'] = $this->randomMachineName(8);
     $edit['comment_body[0][value]'] = $this->randomMachineName(16);
     $this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit, t('Preview'));
     $this->drupalPostForm(NULL, array(), t('Save'));
     $this->assertText(t('Your comment has been posted.'));
     $comments = entity_load_multiple_by_properties('comment', array('subject' => $edit['subject[0][value]']));
     $comment = reset($comments);
     $this->assertTrue($comment->id(), 'Comment found.');
     // Create a node with two revisions, the initial one belonging to the
     // cancelling user.
     $revision_node = $this->drupalCreateNode(array('uid' => $account->id()));
     $revision = $revision_node->getRevisionId();
     $settings = get_object_vars($revision_node);
     $settings['revision'] = 1;
     $settings['uid'] = 1;
     // Set new/current revision to someone else.
     $revision_node = $this->drupalCreateNode($settings);
     // Attempt to cancel account.
     $this->drupalGet('user/' . $account->id() . '/edit');
     $this->drupalPostForm(NULL, NULL, t('Cancel account'));
     $this->assertText(t('Are you sure you want to cancel your account?'), 'Confirmation form to cancel account displayed.');
     $this->assertText(t('Your account will be removed and all account information deleted. All of your content will also be deleted.'), 'Informs that all content will be deleted.');
     // Confirm account cancellation.
     $timestamp = time();
     $this->drupalPostForm(NULL, NULL, t('Cancel account'));
     $this->assertText(t('A confirmation request to cancel your account has been sent to your email address.'), 'Account cancellation request mailed message displayed.');
     // Confirm account cancellation request.
     $this->drupalGet("user/" . $account->id() . "/cancel/confirm/{$timestamp}/" . user_pass_rehash($account, $timestamp));
     $user_storage->resetCache(array($account->id()));
     $this->assertFalse($user_storage->load($account->id()), 'User is not found in the database.');
     // Confirm that user's content has been deleted.
     $node_storage->resetCache(array($node->id()));
     $this->assertFalse($node_storage->load($node->id()), 'Node of the user has been deleted.');
     $this->assertFalse(node_revision_load($revision), 'Node revision of the user has been deleted.');
     $node_storage->resetCache(array($revision_node->id()));
     $this->assertTrue($node_storage->load($revision_node->id()), "Current revision of the user's node was not deleted.");
     \Drupal::entityManager()->getStorage('comment')->resetCache(array($comment->id()));
     $this->assertFalse(Comment::load($comment->id()), 'Comment of the user has been deleted.');
     // Confirm that the confirmation message made it through to the end user.
     $this->assertRaw(t('%name has been deleted.', array('%name' => $account->getUsername())), "Confirmation message displayed to user.");
 }
 /**
  * Tests the comment interface.
  */
 function testCommentInterface()
 {
     // Set comments to have subject and preview disabled.
     $this->drupalLogin($this->admin_user);
     $this->setCommentPreview(DRUPAL_DISABLED);
     $this->setCommentForm(TRUE);
     $this->setCommentSubject(FALSE);
     $this->setCommentSettings('default_mode', CommentManagerInterface::COMMENT_MODE_THREADED, 'Comment paging changed.');
     $this->drupalLogout();
     // Post comment #1 without subject or preview.
     $this->drupalLogin($this->web_user);
     $comment_text = $this->randomMachineName();
     $comment = $this->postComment($this->node, $comment_text);
     $this->assertTrue($this->commentExists($comment), 'Comment found.');
     // Set comments to have subject and preview to required.
     $this->drupalLogout();
     $this->drupalLogin($this->admin_user);
     $this->setCommentSubject(TRUE);
     $this->setCommentPreview(DRUPAL_REQUIRED);
     $this->drupalLogout();
     // Create comment #2 that allows subject and requires preview.
     $this->drupalLogin($this->web_user);
     $subject_text = $this->randomMachineName();
     $comment_text = $this->randomMachineName();
     $comment = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
     $this->assertTrue($this->commentExists($comment), 'Comment found.');
     // Comment as anonymous with preview required.
     $this->drupalLogout();
     user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content', 'access comments', 'post comments', 'skip comment approval'));
     $anonymous_comment = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
     $this->assertTrue($this->commentExists($anonymous_comment), 'Comment found.');
     $anonymous_comment->delete();
     // Check comment display.
     $this->drupalLogin($this->web_user);
     $this->drupalGet('node/' . $this->node->id());
     $this->assertText($subject_text, 'Individual comment subject found.');
     $this->assertText($comment_text, 'Individual comment body found.');
     // Set comments to have subject and preview to optional.
     $this->drupalLogout();
     $this->drupalLogin($this->admin_user);
     $this->setCommentSubject(TRUE);
     $this->setCommentPreview(DRUPAL_OPTIONAL);
     $this->drupalGet('comment/' . $comment->id() . '/edit');
     $this->assertTitle(t('Edit comment @title | Drupal', array('@title' => $comment->getSubject())));
     // Test changing the comment author to "Anonymous".
     $comment = $this->postComment(NULL, $comment->comment_body->value, $comment->getSubject(), array('name' => ''));
     $this->assertTrue($comment->getAuthorName() == t('Anonymous') && $comment->getOwnerId() == 0, 'Comment author successfully changed to anonymous.');
     // Test changing the comment author to an unverified user.
     $random_name = $this->randomMachineName();
     $this->drupalGet('comment/' . $comment->id() . '/edit');
     $comment = $this->postComment(NULL, $comment->comment_body->value, $comment->getSubject(), array('name' => $random_name));
     $this->drupalGet('node/' . $this->node->id());
     $this->assertText($random_name . ' (' . t('not verified') . ')', 'Comment author successfully changed to an unverified user.');
     // Test changing the comment author to a verified user.
     $this->drupalGet('comment/' . $comment->id() . '/edit');
     $comment = $this->postComment(NULL, $comment->comment_body->value, $comment->getSubject(), array('name' => $this->web_user->getUsername()));
     $this->assertTrue($comment->getAuthorName() == $this->web_user->getUsername() && $comment->getOwnerId() == $this->web_user->id(), 'Comment author successfully changed to a registered user.');
     $this->drupalLogout();
     // Reply to comment #2 creating comment #3 with optional preview and no
     // subject though field enabled.
     $this->drupalLogin($this->web_user);
     // Deliberately use the wrong url to test
     // \Drupal\comment\Controller\CommentController::redirectNode().
     $this->drupalGet('comment/' . $this->node->id() . '/reply');
     // Verify we were correctly redirected.
     $this->assertUrl(url('comment/reply/node/' . $this->node->id() . '/comment', array('absolute' => TRUE)));
     $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment->id());
     $this->assertText($subject_text, 'Individual comment-reply subject found.');
     $this->assertText($comment_text, 'Individual comment-reply body found.');
     $reply = $this->postComment(NULL, $this->randomMachineName(), '', TRUE);
     $reply_loaded = Comment::load($reply->id());
     $this->assertTrue($this->commentExists($reply, TRUE), 'Reply found.');
     $this->assertEqual($comment->id(), $reply_loaded->getParentComment()->id(), 'Pid of a reply to a comment is set correctly.');
     // Check the thread of reply grows correctly.
     $this->assertEqual(rtrim($comment->getThread(), '/') . '.00/', $reply_loaded->getThread());
     // Second reply to comment #2 creating comment #4.
     $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $comment->id());
     $this->assertText($comment->getSubject(), 'Individual comment-reply subject found.');
     $this->assertText($comment->comment_body->value, 'Individual comment-reply body found.');
     $reply = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName(), TRUE);
     $reply_loaded = Comment::load($reply->id());
     $this->assertTrue($this->commentExists($reply, TRUE), 'Second reply found.');
     // Check the thread of second reply grows correctly.
     $this->assertEqual(rtrim($comment->getThread(), '/') . '.01/', $reply_loaded->getThread());
     // Reply to comment #4 creating comment #5.
     $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $reply_loaded->id());
     $this->assertText($reply_loaded->getSubject(), 'Individual comment-reply subject found.');
     $this->assertText($reply_loaded->comment_body->value, 'Individual comment-reply body found.');
     $reply = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName(), TRUE);
     $reply_loaded = Comment::load($reply->id());
     $this->assertTrue($this->commentExists($reply, TRUE), 'Second reply found.');
     // Check the thread of reply to second reply grows correctly.
     $this->assertEqual(rtrim($comment->getThread(), '/') . '.01.00/', $reply_loaded->getThread());
     // Edit reply.
     $this->drupalGet('comment/' . $reply->id() . '/edit');
     $reply = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName(), TRUE);
     $this->assertTrue($this->commentExists($reply, TRUE), 'Modified reply found.');
     // Confirm a new comment is posted to the correct page.
     $this->setCommentsPerPage(2);
     $comment_new_page = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
     $this->assertTrue($this->commentExists($comment_new_page), 'Page one exists. %s');
     $this->drupalGet('node/' . $this->node->id(), array('query' => array('page' => 2)));
     $this->assertTrue($this->commentExists($reply, TRUE), 'Page two exists. %s');
     $this->setCommentsPerPage(50);
     // Attempt to reply to an unpublished comment.
     $reply_loaded->setPublished(FALSE);
     $reply_loaded->save();
     $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment/' . $reply_loaded->id());
     $this->assertText(t('The comment you are replying to does not exist.'), 'Replying to an unpublished comment');
     // Attempt to post to node with comments disabled.
     $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => array(array('status' => CommentItemInterface::HIDDEN))));
     $this->assertTrue($this->node, 'Article node created.');
     $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment');
     $this->assertText('This discussion is closed', 'Posting to node with comments disabled');
     $this->assertNoField('edit-comment', 'Comment body field found.');
     // Attempt to post to node with read-only comments.
     $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => array(array('status' => CommentItemInterface::CLOSED))));
     $this->assertTrue($this->node, 'Article node created.');
     $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment');
     $this->assertText('This discussion is closed', 'Posting to node with comments read-only');
     $this->assertNoField('edit-comment', 'Comment body field found.');
     // Attempt to post to node with comments enabled (check field names etc).
     $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => array(array('status' => CommentItemInterface::OPEN))));
     $this->assertTrue($this->node, 'Article node created.');
     $this->drupalGet('comment/reply/node/' . $this->node->id() . '/comment');
     $this->assertNoText('This discussion is closed', 'Posting to node with comments enabled');
     $this->assertField('edit-comment-body-0-value', 'Comment body field found.');
     // Delete comment and make sure that reply is also removed.
     $this->drupalLogout();
     $this->drupalLogin($this->admin_user);
     $this->deleteComment($comment);
     $this->deleteComment($comment_new_page);
     $this->drupalGet('node/' . $this->node->id());
     $this->assertFalse($this->commentExists($comment), 'Comment not found.');
     $this->assertFalse($this->commentExists($reply, TRUE), 'Reply not found.');
     // Enabled comment form on node page.
     $this->drupalLogin($this->admin_user);
     $this->setCommentForm(TRUE);
     $this->drupalLogout();
     // Submit comment through node form.
     $this->drupalLogin($this->web_user);
     $this->drupalGet('node/' . $this->node->id());
     $form_comment = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName(), TRUE);
     $this->assertTrue($this->commentExists($form_comment), 'Form comment found.');
     // Disable comment form on node page.
     $this->drupalLogout();
     $this->drupalLogin($this->admin_user);
     $this->setCommentForm(FALSE);
 }
 /**
  * Tests that download restrictions on private files work on comments.
  */
 function testPrivateFileComment()
 {
     $user = $this->drupalCreateUser(array('access comments'));
     // Grant the admin user required comment permissions.
     $roles = $this->adminUser->getRoles();
     user_role_grant_permissions($roles[1], array('administer comment fields', 'administer comments'));
     // Revoke access comments permission from anon user, grant post to
     // authenticated.
     user_role_revoke_permissions(RoleInterface::ANONYMOUS_ID, array('access comments'));
     user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, array('post comments', 'skip comment approval'));
     // Create a new field.
     $this->addDefaultCommentField('node', 'article');
     $name = strtolower($this->randomMachineName());
     $label = $this->randomMachineName();
     $storage_edit = array('settings[uri_scheme]' => 'private');
     $this->fieldUIAddNewField('admin/structure/comment/manage/comment', $name, $label, 'file', $storage_edit);
     // Manually clear cache on the tester side.
     \Drupal::entityManager()->clearCachedFieldDefinitions();
     // Create node.
     $edit = array('title[0][value]' => $this->randomMachineName());
     $this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
     $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
     // Add a comment with a file.
     $text_file = $this->getTestFile('text');
     $edit = array('files[field_' . $name . '_' . 0 . ']' => drupal_realpath($text_file->getFileUri()), 'comment_body[0][value]' => $comment_body = $this->randomMachineName());
     $this->drupalPostForm('node/' . $node->id(), $edit, t('Save'));
     // Get the comment ID.
     preg_match('/comment-([0-9]+)/', $this->getUrl(), $matches);
     $cid = $matches[1];
     // Log in as normal user.
     $this->drupalLogin($user);
     $comment = Comment::load($cid);
     $comment_file = $comment->{'field_' . $name}->entity;
     $this->assertFileExists($comment_file, 'New file saved to disk on node creation.');
     // Test authenticated file download.
     $url = file_create_url($comment_file->getFileUri());
     $this->assertNotEqual($url, NULL, 'Confirmed that the URL is valid');
     $this->drupalGet(file_create_url($comment_file->getFileUri()));
     $this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
     // Test anonymous file download.
     $this->drupalLogout();
     $this->drupalGet(file_create_url($comment_file->getFileUri()));
     $this->assertResponse(403, 'Confirmed that access is denied for the file without the needed permission.');
     // Unpublishes node.
     $this->drupalLogin($this->adminUser);
     $this->drupalPostForm('node/' . $node->id() . '/edit', array(), t('Save and unpublish'));
     // Ensures normal user can no longer download the file.
     $this->drupalLogin($user);
     $this->drupalGet(file_create_url($comment_file->getFileUri()));
     $this->assertResponse(403, 'Confirmed that access is denied for the file without the needed permission.');
 }
 /**
  * Creates a comment, then tests the tokens generated from it.
  */
 function testCommentTokenReplacement()
 {
     $token_service = \Drupal::token();
     $language_interface = \Drupal::languageManager()->getCurrentLanguage();
     $url_options = array('absolute' => TRUE, 'language' => $language_interface);
     $this->drupalLogin($this->adminUser);
     // Set comment variables.
     $this->setCommentSubject(TRUE);
     // Create a node and a comment.
     $node = $this->drupalCreateNode(array('type' => 'article'));
     $parent_comment = $this->postComment($node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
     // Post a reply to the comment.
     $this->drupalGet('comment/reply/node/' . $node->id() . '/comment/' . $parent_comment->id());
     $child_comment = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName());
     $comment = Comment::load($child_comment->id());
     $comment->setHomepage('http://example.org/');
     // Add HTML to ensure that sanitation of some fields tested directly.
     $comment->setSubject('<blink>Blinking Comment</blink>');
     // Generate and test sanitized tokens.
     $tests = array();
     $tests['[comment:cid]'] = $comment->id();
     $tests['[comment:hostname]'] = SafeMarkup::checkPlain($comment->getHostname());
     $tests['[comment:author]'] = Xss::filter($comment->getAuthorName());
     $tests['[comment:mail]'] = SafeMarkup::checkPlain($this->adminUser->getEmail());
     $tests['[comment:homepage]'] = check_url($comment->getHomepage());
     $tests['[comment:title]'] = Xss::filter($comment->getSubject());
     $tests['[comment:body]'] = $comment->comment_body->processed;
     $tests['[comment:langcode]'] = SafeMarkup::checkPlain($comment->language()->getId());
     $tests['[comment:url]'] = $comment->url('canonical', $url_options + array('fragment' => 'comment-' . $comment->id()));
     $tests['[comment:edit-url]'] = $comment->url('edit-form', $url_options);
     $tests['[comment:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getCreatedTime(), array('langcode' => $language_interface->getId()));
     $tests['[comment:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getChangedTimeAcrossTranslations(), array('langcode' => $language_interface->getId()));
     $tests['[comment:parent:cid]'] = $comment->hasParentComment() ? $comment->getParentComment()->id() : NULL;
     $tests['[comment:parent:title]'] = SafeMarkup::checkPlain($parent_comment->getSubject());
     $tests['[comment:entity]'] = SafeMarkup::checkPlain($node->getTitle());
     // Test node specific tokens.
     $tests['[comment:entity:nid]'] = $comment->getCommentedEntityId();
     $tests['[comment:entity:title]'] = SafeMarkup::checkPlain($node->getTitle());
     $tests['[comment:author:uid]'] = $comment->getOwnerId();
     $tests['[comment:author:name]'] = SafeMarkup::checkPlain($this->adminUser->getUsername());
     // Test to make sure that we generated something for each token.
     $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
     foreach ($tests as $input => $expected) {
         $output = $token_service->replace($input, array('comment' => $comment), array('langcode' => $language_interface->getId()));
         $this->assertEqual($output, $expected, format_string('Sanitized comment token %token replaced.', array('%token' => $input)));
     }
     // Generate and test unsanitized tokens.
     $tests['[comment:hostname]'] = $comment->getHostname();
     $tests['[comment:author]'] = $comment->getAuthorName();
     $tests['[comment:mail]'] = $this->adminUser->getEmail();
     $tests['[comment:homepage]'] = $comment->getHomepage();
     $tests['[comment:title]'] = $comment->getSubject();
     $tests['[comment:body]'] = $comment->comment_body->value;
     $tests['[comment:langcode]'] = $comment->language()->getId();
     $tests['[comment:parent:title]'] = $parent_comment->getSubject();
     $tests['[comment:entity]'] = $node->getTitle();
     $tests['[comment:author:name]'] = $this->adminUser->getUsername();
     foreach ($tests as $input => $expected) {
         $output = $token_service->replace($input, array('comment' => $comment), array('langcode' => $language_interface->getId(), 'sanitize' => FALSE));
         $this->assertEqual($output, $expected, format_string('Unsanitized comment token %token replaced.', array('%token' => $input)));
     }
     // Test anonymous comment author.
     $author_name = $this->randomString();
     $comment->setOwnerId(0)->setAuthorName($author_name);
     $input = '[comment:author]';
     $output = $token_service->replace($input, array('comment' => $comment), array('langcode' => $language_interface->getId()));
     $this->assertEqual($output, Xss::filter($author_name), format_string('Sanitized comment author token %token replaced.', array('%token' => $input)));
     $output = $token_service->replace($input, array('comment' => $comment), array('langcode' => $language_interface->getId(), 'sanitize' => FALSE));
     $this->assertEqual($output, $author_name, format_string('Unsanitized comment author token %token replaced.', array('%token' => $input)));
     // Load node so comment_count gets computed.
     $node = Node::load($node->id());
     // Generate comment tokens for the node (it has 2 comments, both new).
     $tests = array();
     $tests['[entity:comment-count]'] = 2;
     $tests['[entity:comment-count-new]'] = 2;
     foreach ($tests as $input => $expected) {
         $output = $token_service->replace($input, array('entity' => $node, 'node' => $node), array('langcode' => $language_interface->getId()));
         $this->assertEqual($output, $expected, format_string('Node comment token %token replaced.', array('%token' => $input)));
     }
 }
 /**
  * Tests hook invocations for CRUD operations on comments.
  */
 public function testCommentHooks()
 {
     $account = $this->createUser();
     entity_create('node_type', array('type' => 'article', 'name' => 'Article'))->save();
     $this->addDefaultCommentField('node', 'article', 'comment', CommentItemInterface::OPEN);
     $node = entity_create('node', array('uid' => $account->id(), 'type' => 'article', 'title' => 'Test node', 'status' => 1, 'promote' => 0, 'sticky' => 0, 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, 'created' => REQUEST_TIME, 'changed' => REQUEST_TIME));
     $node->save();
     $nid = $node->id();
     $GLOBALS['entity_crud_hook_test'] = array();
     $comment = entity_create('comment', array('cid' => NULL, 'pid' => 0, 'entity_id' => $nid, 'entity_type' => 'node', 'field_name' => 'comment', 'uid' => $account->id(), 'subject' => 'Test comment', 'created' => REQUEST_TIME, 'changed' => REQUEST_TIME, 'status' => 1, 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED));
     $this->assertHookMessageOrder(array('entity_crud_hook_test_comment_create called', 'entity_crud_hook_test_entity_create called for type comment'));
     $GLOBALS['entity_crud_hook_test'] = array();
     $comment->save();
     $this->assertHookMessageOrder(array('entity_crud_hook_test_comment_presave called', 'entity_crud_hook_test_entity_presave called for type comment', 'entity_crud_hook_test_comment_insert called', 'entity_crud_hook_test_entity_insert called for type comment'));
     $GLOBALS['entity_crud_hook_test'] = array();
     $comment = Comment::load($comment->id());
     $this->assertHookMessageOrder(array('entity_crud_hook_test_entity_load called for type comment', 'entity_crud_hook_test_comment_load called'));
     $GLOBALS['entity_crud_hook_test'] = array();
     $comment->setSubject('New subject');
     $comment->save();
     $this->assertHookMessageOrder(array('entity_crud_hook_test_comment_presave called', 'entity_crud_hook_test_entity_presave called for type comment', 'entity_crud_hook_test_comment_update called', 'entity_crud_hook_test_entity_update called for type comment'));
     $GLOBALS['entity_crud_hook_test'] = array();
     $comment->delete();
     $this->assertHookMessageOrder(array('entity_crud_hook_test_comment_predelete called', 'entity_crud_hook_test_entity_predelete called for type comment', 'entity_crud_hook_test_comment_delete called', 'entity_crud_hook_test_entity_delete called for type comment'));
 }
 /**
  * Test that automatic subject is correctly created from HTML comment text.
  *
  * This is the same test as in CommentInterfaceTest::testAutoFilledSubject()
  * with the additional check that HTML is stripped appropriately prior to
  * character-counting.
  */
 public function testAutoFilledHtmlSubject()
 {
     // Set up two default (i.e. filtered HTML) input formats, because then we
     // can select one of them. Then create a user that can use these formats,
     // log the user in, and then GET the node page on which to test the
     // comments.
     $filtered_html_format = FilterFormat::create(array('format' => 'filtered_html', 'name' => 'Filtered HTML'));
     $filtered_html_format->save();
     $full_html_format = FilterFormat::create(array('format' => 'full_html', 'name' => 'Full HTML'));
     $full_html_format->save();
     $html_user = $this->drupalCreateUser(array('access comments', 'post comments', 'edit own comments', 'skip comment approval', 'access content', $filtered_html_format->getPermissionName(), $full_html_format->getPermissionName()));
     $this->drupalLogin($html_user);
     $this->drupalGet('node/' . $this->node->id());
     // HTML should not be included in the character count.
     $body_text1 = '<span></span><strong> </strong><span> </span><strong></strong>Hello World<br />';
     $edit1 = array('comment_body[0][value]' => $body_text1, 'comment_body[0][format]' => 'filtered_html');
     $this->drupalPostForm(NULL, $edit1, t('Save'));
     $this->assertEqual('Hello World', Comment::load(1)->getSubject());
     // If there's nothing other than HTML, the subject should be '(No subject)'.
     $body_text2 = '<span></span><strong> </strong><span> </span><strong></strong> <br />';
     $edit2 = array('comment_body[0][value]' => $body_text2, 'comment_body[0][format]' => 'filtered_html');
     $this->drupalPostForm(NULL, $edit2, t('Save'));
     $this->assertEqual('(No subject)', Comment::load(2)->getSubject());
 }
 /**
  * Tests comment edit, preview, and save.
  */
 function testCommentEditPreviewSave()
 {
     $web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'skip comment approval', 'edit own comments'));
     $this->drupalLogin($this->adminUser);
     $this->setCommentPreview(DRUPAL_OPTIONAL);
     $this->setCommentForm(TRUE);
     $this->setCommentSubject(TRUE);
     $this->setCommentSettings('default_mode', CommentManagerInterface::COMMENT_MODE_THREADED, 'Comment paging changed.');
     $edit = array();
     $date = new DrupalDateTime('2008-03-02 17:23');
     $edit['subject[0][value]'] = $this->randomMachineName(8);
     $edit['comment_body[0][value]'] = $this->randomMachineName(16);
     $edit['uid'] = $web_user->getUsername() . ' (' . $web_user->id() . ')';
     $edit['date[date]'] = $date->format('Y-m-d');
     $edit['date[time]'] = $date->format('H:i:s');
     $raw_date = $date->getTimestamp();
     $expected_text_date = format_date($raw_date);
     $expected_form_date = $date->format('Y-m-d');
     $expected_form_time = $date->format('H:i:s');
     $comment = $this->postComment($this->node, $edit['subject[0][value]'], $edit['comment_body[0][value]'], TRUE);
     $this->drupalPostForm('comment/' . $comment->id() . '/edit', $edit, t('Preview'));
     // Check that the preview is displaying the subject, comment, author and date correctly.
     $this->assertTitle(t('Preview comment | Drupal'), 'Page title is "Preview comment".');
     $this->assertText($edit['subject[0][value]'], 'Subject displayed.');
     $this->assertText($edit['comment_body[0][value]'], 'Comment displayed.');
     $this->assertText($web_user->getUsername(), 'Author displayed.');
     $this->assertText($expected_text_date, 'Date displayed.');
     // Check that the subject, comment, author and date fields are displayed with the correct values.
     $this->assertFieldByName('subject[0][value]', $edit['subject[0][value]'], 'Subject field displayed.');
     $this->assertFieldByName('comment_body[0][value]', $edit['comment_body[0][value]'], 'Comment field displayed.');
     $this->assertFieldByName('uid', $edit['uid'], 'Author field displayed.');
     $this->assertFieldByName('date[date]', $edit['date[date]'], 'Date field displayed.');
     $this->assertFieldByName('date[time]', $edit['date[time]'], 'Time field displayed.');
     // Check that saving a comment produces a success message.
     $this->drupalPostForm('comment/' . $comment->id() . '/edit', $edit, t('Save'));
     $this->assertText(t('Your comment has been posted.'), 'Comment posted.');
     // Check that the comment fields are correct after loading the saved comment.
     $this->drupalGet('comment/' . $comment->id() . '/edit');
     $this->assertFieldByName('subject[0][value]', $edit['subject[0][value]'], 'Subject field displayed.');
     $this->assertFieldByName('comment_body[0][value]', $edit['comment_body[0][value]'], 'Comment field displayed.');
     $this->assertFieldByName('uid', $edit['uid'], 'Author field displayed.');
     $this->assertFieldByName('date[date]', $expected_form_date, 'Date field displayed.');
     $this->assertFieldByName('date[time]', $expected_form_time, 'Time field displayed.');
     // Submit the form using the displayed values.
     $displayed = array();
     $displayed['subject[0][value]'] = (string) current($this->xpath("//input[@id='edit-subject-0-value']/@value"));
     $displayed['comment_body[0][value]'] = (string) current($this->xpath("//textarea[@id='edit-comment-body-0-value']"));
     $displayed['uid'] = (string) current($this->xpath("//input[@id='edit-uid']/@value"));
     $displayed['date[date]'] = (string) current($this->xpath("//input[@id='edit-date-date']/@value"));
     $displayed['date[time]'] = (string) current($this->xpath("//input[@id='edit-date-time']/@value"));
     $this->drupalPostForm('comment/' . $comment->id() . '/edit', $displayed, t('Save'));
     // Check that the saved comment is still correct.
     $comment_storage = \Drupal::entityManager()->getStorage('comment');
     $comment_storage->resetCache(array($comment->id()));
     /** @var \Drupal\comment\CommentInterface $comment_loaded */
     $comment_loaded = Comment::load($comment->id());
     $this->assertEqual($comment_loaded->getSubject(), $edit['subject[0][value]'], 'Subject loaded.');
     $this->assertEqual($comment_loaded->comment_body->value, $edit['comment_body[0][value]'], 'Comment body loaded.');
     $this->assertEqual($comment_loaded->getOwner()->id(), $web_user->id(), 'Name loaded.');
     $this->assertEqual($comment_loaded->getCreatedTime(), $raw_date, 'Date loaded.');
     $this->drupalLogout();
     // Check that the date and time of the comment are correct when edited by
     // non-admin users.
     $user_edit = array();
     $expected_created_time = $comment_loaded->getCreatedTime();
     $this->drupalLogin($web_user);
     // Web user cannot change the comment author.
     unset($edit['uid']);
     $this->drupalPostForm('comment/' . $comment->id() . '/edit', $user_edit, t('Save'));
     $comment_storage->resetCache(array($comment->id()));
     $comment_loaded = Comment::load($comment->id());
     $this->assertEqual($comment_loaded->getCreatedTime(), $expected_created_time, 'Expected date and time for comment edited.');
     $this->drupalLogout();
 }
 /**
  * Test that comment language is properly set.
  */
 function testCommentLanguage()
 {
     // Create two nodes, one for english and one for french, and comment each
     // node using both english and french as content language by changing URL
     // language prefixes. Meanwhile interface language is always French, which
     // is the user language preference. This way we can ensure that node
     // language and interface language do not influence comment language, as
     // only content language has to.
     foreach ($this->container->get('language_manager')->getLanguages() as $node_langcode => $node_language) {
         // Create "Article" content.
         $title = $this->randomMachineName();
         $edit = array('title[0][value]' => $title, 'body[0][value]' => $this->randomMachineName(), 'langcode' => $node_langcode, 'comment[0][status]' => CommentItemInterface::OPEN);
         $this->drupalPostForm("node/add/article", $edit, t('Save'));
         $node = $this->drupalGetNodeByTitle($title);
         $prefixes = language_negotiation_url_prefixes();
         foreach ($this->container->get('language_manager')->getLanguages() as $langcode => $language) {
             // Post a comment with content language $langcode.
             $prefix = empty($prefixes[$langcode]) ? '' : $prefixes[$langcode] . '/';
             $comment_values[$node_langcode][$langcode] = $this->randomMachineName();
             $edit = array('subject[0][value]' => $this->randomMachineName(), 'comment_body[0][value]' => $comment_values[$node_langcode][$langcode]);
             $this->drupalPostForm($prefix . 'node/' . $node->id(), $edit, t('Preview'));
             $this->drupalPostForm(NULL, $edit, t('Save'));
             // Check that comment language matches the current content language.
             $cid = db_select('comment_field_data', 'c')->fields('c', array('cid'))->condition('entity_id', $node->id())->condition('entity_type', 'node')->condition('field_name', 'comment')->condition('default_langcode', 1)->orderBy('cid', 'DESC')->range(0, 1)->execute()->fetchField();
             $comment = Comment::load($cid);
             $args = array('%node_language' => $node_langcode, '%comment_language' => $comment->langcode->value, '%langcode' => $langcode);
             $this->assertEqual($comment->langcode->value, $langcode, format_string('The comment posted with content language %langcode and belonging to the node with language %node_language has language %comment_language', $args));
             $this->assertEqual($comment->comment_body->value, $comment_values[$node_langcode][$langcode], 'Comment body correctly stored.');
         }
     }
     // Check that comment bodies appear in the administration UI.
     $this->drupalGet('admin/content/comment');
     foreach ($comment_values as $node_values) {
         foreach ($node_values as $value) {
             $this->assertRaw($value);
         }
     }
 }
 /**
  * Creates a comment, then tests the tokens generated from it.
  */
 function testCommentTokenReplacement()
 {
     $token_service = \Drupal::token();
     $language_interface = \Drupal::languageManager()->getCurrentLanguage();
     $url_options = array('absolute' => TRUE, 'language' => $language_interface);
     // Change the title of the admin user.
     $this->adminUser->name->value = 'This is a title with some special & > " stuff.';
     $this->adminUser->save();
     $this->drupalLogin($this->adminUser);
     // Set comment variables.
     $this->setCommentSubject(TRUE);
     // Create a node and a comment.
     $node = $this->drupalCreateNode(['type' => 'article', 'title' => '<script>alert("123")</script>']);
     $parent_comment = $this->postComment($node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
     // Post a reply to the comment.
     $this->drupalGet('comment/reply/node/' . $node->id() . '/comment/' . $parent_comment->id());
     $child_comment = $this->postComment(NULL, $this->randomMachineName(), $this->randomMachineName());
     $comment = Comment::load($child_comment->id());
     $comment->setHomepage('http://example.org/');
     // Add HTML to ensure that sanitation of some fields tested directly.
     $comment->setSubject('<blink>Blinking Comment</blink>');
     // Generate and test tokens.
     $tests = array();
     $tests['[comment:cid]'] = $comment->id();
     $tests['[comment:hostname]'] = $comment->getHostname();
     $tests['[comment:author]'] = Html::escape($comment->getAuthorName());
     $tests['[comment:mail]'] = $this->adminUser->getEmail();
     $tests['[comment:homepage]'] = UrlHelper::filterBadProtocol($comment->getHomepage());
     $tests['[comment:title]'] = Html::escape($comment->getSubject());
     $tests['[comment:body]'] = $comment->comment_body->processed;
     $tests['[comment:langcode]'] = $comment->language()->getId();
     $tests['[comment:url]'] = $comment->url('canonical', $url_options + array('fragment' => 'comment-' . $comment->id()));
     $tests['[comment:edit-url]'] = $comment->url('edit-form', $url_options);
     $tests['[comment:created]'] = \Drupal::service('date.formatter')->format($comment->getCreatedTime(), 'medium', array('langcode' => $language_interface->getId()));
     $tests['[comment:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getCreatedTime(), array('langcode' => $language_interface->getId()));
     $tests['[comment:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getChangedTimeAcrossTranslations(), array('langcode' => $language_interface->getId()));
     $tests['[comment:parent:cid]'] = $comment->hasParentComment() ? $comment->getParentComment()->id() : NULL;
     $tests['[comment:parent:title]'] = $parent_comment->getSubject();
     $tests['[comment:entity]'] = Html::escape($node->getTitle());
     // Test node specific tokens.
     $tests['[comment:entity:nid]'] = $comment->getCommentedEntityId();
     $tests['[comment:entity:title]'] = Html::escape($node->getTitle());
     $tests['[comment:author:uid]'] = $comment->getOwnerId();
     $tests['[comment:author:name]'] = Html::escape($this->adminUser->getDisplayName());
     $base_bubbleable_metadata = BubbleableMetadata::createFromObject($comment);
     $metadata_tests = [];
     $metadata_tests['[comment:cid]'] = $base_bubbleable_metadata;
     $metadata_tests['[comment:hostname]'] = $base_bubbleable_metadata;
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $bubbleable_metadata->addCacheableDependency($this->adminUser);
     $metadata_tests['[comment:author]'] = $bubbleable_metadata;
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $bubbleable_metadata->addCacheableDependency($this->adminUser);
     $metadata_tests['[comment:mail]'] = $bubbleable_metadata;
     $metadata_tests['[comment:homepage]'] = $base_bubbleable_metadata;
     $metadata_tests['[comment:title]'] = $base_bubbleable_metadata;
     $metadata_tests['[comment:body]'] = $base_bubbleable_metadata;
     $metadata_tests['[comment:langcode]'] = $base_bubbleable_metadata;
     $metadata_tests['[comment:url]'] = $base_bubbleable_metadata;
     $metadata_tests['[comment:edit-url]'] = $base_bubbleable_metadata;
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $metadata_tests['[comment:created]'] = $bubbleable_metadata->addCacheTags(['rendered']);
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $metadata_tests['[comment:created:since]'] = $bubbleable_metadata->setCacheMaxAge(0);
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $metadata_tests['[comment:changed:since]'] = $bubbleable_metadata->setCacheMaxAge(0);
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $metadata_tests['[comment:parent:cid]'] = $bubbleable_metadata->addCacheTags(['comment:1']);
     $metadata_tests['[comment:parent:title]'] = $bubbleable_metadata;
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $metadata_tests['[comment:entity]'] = $bubbleable_metadata->addCacheTags(['node:2']);
     // Test node specific tokens.
     $metadata_tests['[comment:entity:nid]'] = $bubbleable_metadata;
     $metadata_tests['[comment:entity:title]'] = $bubbleable_metadata;
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $metadata_tests['[comment:author:uid]'] = $bubbleable_metadata->addCacheTags(['user:2']);
     $metadata_tests['[comment:author:name]'] = $bubbleable_metadata;
     // Test to make sure that we generated something for each token.
     $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
     foreach ($tests as $input => $expected) {
         $bubbleable_metadata = new BubbleableMetadata();
         $output = $token_service->replace($input, array('comment' => $comment), array('langcode' => $language_interface->getId()), $bubbleable_metadata);
         $this->assertEqual($output, $expected, new FormattableMarkup('Comment token %token replaced.', ['%token' => $input]));
         $this->assertEqual($bubbleable_metadata, $metadata_tests[$input]);
     }
     // Test anonymous comment author.
     $author_name = 'This is a random & " > string';
     $comment->setOwnerId(0)->setAuthorName($author_name);
     $input = '[comment:author]';
     $output = $token_service->replace($input, array('comment' => $comment), array('langcode' => $language_interface->getId()));
     $this->assertEqual($output, Html::escape($author_name), format_string('Comment author token %token replaced.', array('%token' => $input)));
     // Load node so comment_count gets computed.
     $node = Node::load($node->id());
     // Generate comment tokens for the node (it has 2 comments, both new).
     $tests = array();
     $tests['[entity:comment-count]'] = 2;
     $tests['[entity:comment-count-new]'] = 2;
     foreach ($tests as $input => $expected) {
         $output = $token_service->replace($input, array('entity' => $node, 'node' => $node), array('langcode' => $language_interface->getId()));
         $this->assertEqual($output, $expected, format_string('Node comment token %token replaced.', array('%token' => $input)));
     }
 }