Commit fdba1d63 authored by catch's avatar catch

Issue #2155387 by larowlan: Multiple comment fields per entity are supported,...

Issue #2155387 by larowlan: Multiple comment fields per entity are supported, but break horribly when they need pagers.
parent d443c10c
......@@ -599,6 +599,9 @@ function comment_add(EntityInterface $entity, $field_name = 'comment', $pid = NU
* The comment display mode; COMMENT_MODE_FLAT or COMMENT_MODE_THREADED.
* @param int $comments_per_page
* The amount of comments to display per page.
* @param int $pager_id
* (optional) Pager id to use in case of multiple pagers on the one page.
* Defaults to 0.
*
* @return
* An array of the IDs of the comment to be displayed.
......@@ -657,9 +660,12 @@ function comment_add(EntityInterface $entity, $field_name = 'comment', $pid = NU
* spoil the reverse ordering, "ORDER BY thread ASC" -- here, we do not need
* to consider the trailing "/" so we use a substring only.
*/
function comment_get_thread(EntityInterface $entity, $field_name, $mode, $comments_per_page) {
function comment_get_thread(EntityInterface $entity, $field_name, $mode, $comments_per_page, $pager_id = 0) {
$query = db_select('comment', 'c')
->extend('Drupal\Core\Database\Query\PagerSelectExtender');
if ($pager_id) {
$query->element($pager_id);
}
$query->addField('c', 'cid');
$query
->condition('c.entity_id', $entity->id())
......
......@@ -28,6 +28,9 @@
* },
* edit = {
* "editor" = "disabled"
* },
* settings = {
* "pager_id" = 0
* }
* )
*/
......@@ -88,12 +91,12 @@ public static function create(ContainerInterface $container, array $configuratio
* The view mode.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param \Drupal\comment\CommentStorageControllerInterface
* @param \Drupal\comment\CommentStorageControllerInterface $comment_storage_controller
* The comment storage controller.
* @param \Drupal\Core\Entity\EntityViewBuilderInterface
* @param \Drupal\Core\Entity\EntityViewBuilderInterface $comment_view_builder
* The comment view builder.
*/
public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, AccountInterface $current_user, CommentStorageControllerInterface $comment_storage_controller, EntityViewBuilderInterface $comment_view_builder) {
public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, AccountInterface $current_user, CommentStorageControllerInterface $comment_storage_controller, EntityViewBuilderInterface $comment_view_builder) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode);
$this->viewBuilder = $comment_view_builder;
$this->storageController = $comment_storage_controller;
......@@ -127,11 +130,14 @@ public function viewElements(FieldItemListInterface $items) {
$this->currentUser->hasPermission('administer comments'))) {
$mode = $comment_settings['default_mode'];
$comments_per_page = $comment_settings['per_page'];
if ($cids = comment_get_thread($entity, $field_name, $mode, $comments_per_page)) {
if ($cids = comment_get_thread($entity, $field_name, $mode, $comments_per_page, $this->settings['pager_id'])) {
$comments = $this->storageController->loadMultiple($cids);
comment_prepare_thread($comments);
$build = $this->viewBuilder->viewMultiple($comments);
$build['pager']['#theme'] = 'pager';
if (!empty($this->settings['pager_id'])) {
$build['pager']['#element'] = $this->settings['pager_id'];
}
$output['comments'] = $build;
}
}
......@@ -155,7 +161,7 @@ public function viewElements(FieldItemListInterface $items) {
'#context' => array(
'entity_type' => $entity->entityType(),
'entity_id' => $entity->id(),
'field_name' => $field_name
'field_name' => $field_name,
),
);
}
......@@ -191,4 +197,32 @@ public static function renderForm(array $context) {
return comment_add($entity, $context['field_name']);
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, array &$form_state) {
$element = array();
$element['pager_id'] = array(
'#type' => 'select',
'#title' => $this->t('Pager ID'),
'#options' => range(0, 10),
'#default_value' => empty($this->settings['pager_id']) ? 0 : $this->settings['pager_id'],
'#description' => $this->t("Unless you're experiencing problems with pagers related to this field, you should leave this at 0. If using multiple pagers on one page you may need to set this number to a higher value so as not to conflict within the ?page= array. Large values will add a lot of commas to your URLs, so avoid if possible."),
);
return $element;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
// Only show a summary if we're using a non-standard pager id.
if (!empty($this->settings['pager_id'])) {
return array($this->t('Pager ID: @id', array(
'@id' => $this->settings['pager_id'],
)));
}
return array();
}
}
......@@ -268,4 +268,69 @@ function testCommentNewPageIndicator() {
$this->assertEqual($expected_page, $returned_page, format_string('Threaded mode, @new replies: expected page @expected, returned page @returned.', array('@new' => $new_replies, '@expected' => $expected_page, '@returned' => $returned_page)));
}
}
/**
* Confirms comment paging works correctly with two pagers.
*/
function testTwoPagers() {
$this->drupalLogin($this->admin_user);
// Add another field to article content-type.
$this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment_2');
// Set default to display comment list with unique pager id.
entity_get_display('node', 'article', 'default')
->setComponent('comment_2', array(
'label' => 'hidden',
'type' => 'comment_default',
'weight' => 20,
'settings' => array(
'pager_id' => 1,
)
))
->save();
// Add a new node with both comment fields open.
$node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->web_user->id()));
// Set comment options.
$comments = array();
foreach (array('comment', 'comment_2') as $field_name) {
$this->setCommentForm(TRUE, $field_name);
$this->setCommentSubject(TRUE, $field_name);
$this->setCommentPreview(DRUPAL_OPTIONAL, $field_name);
$this->setCommentSettings('default_mode', COMMENT_MODE_FLAT, 'Comment paging changed.', $field_name);
// Set comments to one per page so that we are able to test paging without
// needing to insert large numbers of comments.
$this->setCommentsPerPage(1, $field_name);
for ($i = 0; $i < 3; $i++) {
$comment = t('Comment @count on field @field', array(
'@count' => $i + 1,
'@field' => $field_name,
));
$comments[] = $this->postComment($node, $comment, $comment, TRUE, $field_name);
}
}
// Check the first page of the node, and confirm the correct comments are
// shown.
$this->drupalGet('node/' . $node->id());
$this->assertRaw(t('next'), 'Paging links found.');
$this->assertRaw('Comment 1 on field comment');
$this->assertRaw('Comment 1 on field comment_2');
// Navigate to next page of field 1.
$this->clickLink('next ›');
// Check only one pager updated.
$this->assertRaw('Comment 2 on field comment');
$this->assertRaw('Comment 1 on field comment_2');
// Return to page 1.
$this->drupalGet('node/' . $node->id());
// Navigate to next page of field 2.
$this->clickLink('next ›', 1);
// Check only one pager updated.
$this->assertRaw('Comment 1 on field comment');
$this->assertRaw('Comment 2 on field comment_2');
// Navigate to next page of field 1.
$this->clickLink('next ›');
// Check only one pager updated.
$this->assertRaw('Comment 2 on field comment');
$this->assertRaw('Comment 2 on field comment_2');
}
}
......@@ -86,33 +86,36 @@ function setUp() {
*
* @param \Drupal\Core\Entity\EntityInterface|null $entity
* Node to post comment on or NULL to post to the previously loaded page.
* @param $comment
* @param string $comment
* Comment body.
* @param $subject
* @param string $subject
* Comment subject.
* @param $contact
* @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.
*/
function postComment($entity, $comment, $subject = '', $contact = NULL) {
public function postComment($entity, $comment, $subject = '', $contact = NULL, $field_name = 'comment') {
$edit = array();
$edit['comment_body[0][value]'] = $comment;
if ($entity !== NULL) {
$instance = $this->container->get('field.info')->getInstance('node', $entity->bundle(), 'comment');
$instance = $this->container->get('field.info')->getInstance('node', $entity->bundle(), $field_name);
}
else {
$instance = $this->container->get('field.info')->getInstance('node', 'article', 'comment');
$instance = $this->container->get('field.info')->getInstance('node', 'article', $field_name);
}
$preview_mode = $instance->settings['preview'];
$subject_mode = $instance->settings['subject'];
// Must get the page before we test for fields.
if ($entity !== NULL) {
$this->drupalGet('comment/reply/node/' . $entity->id() . '/comment');
$this->drupalGet('comment/reply/node/' . $entity->id() . '/' . $field_name);
}
if ($subject_mode == TRUE) {
......@@ -202,11 +205,14 @@ function deleteComment(CommentInterface $comment) {
/**
* Sets the value governing whether the subject field should be enabled.
*
* @param boolean $enabled
* @param bool $enabled
* Boolean specifying whether the subject field should be enabled.
* @param string $field_name
* (optional) Field name through which the comment should be posted.
* Defaults to 'comment'.
*/
function setCommentSubject($enabled) {
$this->setCommentSettings('subject', ($enabled ? '1' : '0'), 'Comment subject ' . ($enabled ? 'enabled' : 'disabled') . '.');
public function setCommentSubject($enabled, $field_name = 'comment') {
$this->setCommentSettings('subject', ($enabled ? '1' : '0'), 'Comment subject ' . ($enabled ? 'enabled' : 'disabled') . '.', $field_name);
}
/**
......@@ -214,8 +220,11 @@ function setCommentSubject($enabled) {
*
* @param int $mode
* The preview mode: DRUPAL_DISABLED, DRUPAL_OPTIONAL or DRUPAL_REQUIRED.
* @param string $field_name
* (optional) Field name through which the comment should be posted.
* Defaults to 'comment'.
*/
function setCommentPreview($mode) {
public function setCommentPreview($mode, $field_name = 'comment') {
switch ($mode) {
case DRUPAL_DISABLED:
$mode_text = 'disabled';
......@@ -229,18 +238,21 @@ function setCommentPreview($mode) {
$mode_text = 'required';
break;
}
$this->setCommentSettings('preview', $mode, format_string('Comment preview @mode_text.', array('@mode_text' => $mode_text)));
$this->setCommentSettings('preview', $mode, format_string('Comment preview @mode_text.', array('@mode_text' => $mode_text)), $field_name);
}
/**
* Sets the value governing whether the comment form is on its own page.
*
* @param boolean $enabled
* @param bool $enabled
* TRUE if the comment form should be displayed on the same page as the
* comments; FALSE if it should be displayed on its own page.
* @param string $field_name
* (optional) Field name through which the comment should be posted.
* Defaults to 'comment'.
*/
function setCommentForm($enabled) {
$this->setCommentSettings('form_location', ($enabled ? COMMENT_FORM_BELOW : COMMENT_FORM_SEPARATE_PAGE), 'Comment controls ' . ($enabled ? 'enabled' : 'disabled') . '.');
public function setCommentForm($enabled, $field_name = 'comment') {
$this->setCommentSettings('form_location', ($enabled ? COMMENT_FORM_BELOW : COMMENT_FORM_SEPARATE_PAGE), 'Comment controls ' . ($enabled ? 'enabled' : 'disabled') . '.', $field_name);
}
/**
......@@ -259,11 +271,14 @@ function setCommentAnonymous($level) {
/**
* Sets the value specifying the default number of comments per page.
*
* @param integer $comments
* @param int $number
* Comments per page value.
* @param string $field_name
* (optional) Field name through which the comment should be posted.
* Defaults to 'comment'.
*/
function setCommentsPerPage($number) {
$this->setCommentSettings('per_page', $number, format_string('Number of comments per page set to @number.', array('@number' => $number)));
public function setCommentsPerPage($number, $field_name = 'comment') {
$this->setCommentSettings('per_page', $number, format_string('Number of comments per page set to @number.', array('@number' => $number)), $field_name);
}
/**
......@@ -275,9 +290,12 @@ function setCommentsPerPage($number) {
* Value of variable.
* @param string $message
* Status message to display.
* @param string $field_name
* (optional) Field name through which the comment should be posted.
* Defaults to 'comment'.
*/
function setCommentSettings($name, $value, $message) {
$instance = $this->container->get('field.info')->getInstance('node', 'article', 'comment');
public function setCommentSettings($name, $value, $message, $field_name = 'comment') {
$instance = $this->container->get('field.info')->getInstance('node', 'article', $field_name);
$instance->settings[$name] = $value;
$instance->save();
// Display status message.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment