/** * 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]); } }
/** * 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))); } }