Drupal 8 的评论系统具有线程化功能,以便用户可以直接回复其他用户的评论并创建对话线程。我一直觉得这很难使用和阅读,所以我想在我设置这个网站时把它关掉。我遇到的唯一问题是我可以关闭线程,但无法更改评论的顺序。
Drupal 8 中默认的注释排序是按线程排序的。这意味着即使您关闭线程,评论也始终按线程顺序显示。Drupal 使用 CommentDefaultFormatter 类来显示注释并包含这行代码。
$comments = $this->storage->loadThread($entity, $field_name, $mode, $comments_per_page, $this->getSetting('pager_id'));
没有选项可以将其更改loadThread()为其他内容,这意味着只要 Drupal 使用此类来显示注释,它将始终使用此方法。
要覆盖它,我们可以使用自定义 FieldFormatter 插件并使用自定义格式化程序重新排序注释。
在自定义模块中,在 src/Plugin/Field/FieldFormatter/CustomCommentFormatter.php 创建一个类。这是允许我们提供我们自己的自定义评论排序的插件。这个类只是扩展了 CommentDefaultFormatter 类(这是我们想要覆盖的类),所以我们只需要包含我们需要覆盖的方法。
<?php namespace Drupal\custom_comment_module\Plugin\Field\FieldFormatter; use Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter; /** * Provides a custom comment formatter to order comments by date. * * @FieldFormatter( * id = "comment_orderbydate", * module = "comment", * label = @Translation("Custom comment list"), * field_types = { * "comment" * }, * quickedit = { * "editor" = "disabled" * } * ) */ class CustomCommentFormatter extends CommentDefaultFormatter { }
由于在 Drupal 中检索和排序评论的方式,我们需要覆盖 CommentStorage 类以更改评论的加载方式。这可以通过使用 hook_entity_type_alter()更改 Comment 实体的存储处理程序来实现。这将通过以下方式完成。
/** * Implements hook_entity_type_alter(). */ function custom_comment_entity_type_alter(array &$entity_types) { $entity_types['page']->setHandlerClass('storage', CustomCommentStorage::class); }
另一种(也许更简单?)的方法是loadThread()用一些能以我们想要的方式加载注释的东西替换类中的方法。为此,我首先需要修改 CustomCommentFormatter 类,以便通过依赖注入加载到数据库中。虽然看起来我在这里写了很多代码,但实际上只是添加了数据库处理程序,所有其他注入的依赖项已经被 CommentDefaultFormatter 类使用,因此需要包含在内。
<?php namespace Drupal\custom_comment_module\Plugin\Field\FieldFormatter; use Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter; use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\comment\CommentInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Field\FieldItemListInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityFormBuilderInterface; use Drupal\Core\Routing\RouteMatchInterface; /** * Provides a custom comment formatter to order comments by date. * * @FieldFormatter( * id = "comment_orderbydate", * module = "comment", * label = @Translation("Custom comment list"), * field_types = { * "comment" * }, * quickedit = { * "editor" = "disabled" * } * ) */ class CustomCommentFormatter extends CommentDefaultFormatter { /** * The entity form builder. * * @var \Drupal\Core\Database\Connection */ protected $database; /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['label'], $configuration['view_mode'], $configuration['third_party_settings'], $container->get('current_user'), $container->get('entity.manager'), $container->get('entity.form_builder'), $container->get('current_route_match'), $container->get('database') ); } /** * CustomCommentFormatter constructor. * * @param string $plugin_id * The plugin_id for the formatter. * @param mixed $plugin_definition * The plugin implementation definition. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The definition of the field to which the formatter is associated. * @param array $settings * The formatter settings. * @param string $label * The formatter label display setting. * @param string $view_mode * The view mode. * @param array $third_party_settings * Third party settings. * @param \Drupal\Core\Session\AccountInterface $current_user * The current user. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entity_form_builder * The entity form builder. * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The route match object. * @param \Drupal\Core\Database\Connection $database * The database connection to be used. */ public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, EntityManagerInterface $entity_manager, EntityFormBuilderInterface $entity_form_builder, RouteMatchInterface $route_match, Connection $database) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings, $current_user, $entity_manager, $entity_form_builder, $route_match); $this->database = $database; } }
有了这个,我们就可以添加一个自定义loadComments()方法。此方法与 方法非常相似loadThread(),但在这种情况下,它按日期加载评论,按升序排列。
/** * Retrieves comments for a thread, sorted in an order suitable for display. * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity whose comment(s) needs rendering. * @param string $field_name * The field_name whose comment(s) needs rendering. * @param int $mode * The comment display mode: CommentManagerInterface::COMMENT_MODE_FLAT or * CommentManagerInterface::COMMENT_MODE_THREADED. * @param int $comments_per_page * (optional) The amount of comments to display per page. * Defaults to 0, which means show all comments. * @param int $pager_id * (optional) Pager id to use in case of multiple pagers on the one page. * Defaults to 0; is only used when $comments_per_page is greater than zero. * * @return array * Ordered array of comment objects, keyed by comment id. */ public function loadComments(EntityInterface $entity, $field_name, $mode, $comments_per_page = 0, $pager_id = 0) { $query = $this->database->select('comment_field_data', 'c'); $query->addField('c', 'cid'); $query ->condition('c.entity_id', $entity->id()) ->condition('c.entity_type', $entity->getEntityTypeId()) ->condition('c.field_name', $field_name) ->condition('c.default_langcode', 1) ->addTag('entity_access') ->addTag('comment_filter') ->addMetaData('base_table', 'comment') ->addMetaData('entity', $entity) ->addMetaData('field_name', $field_name); if ($comments_per_page) { $query = $query->extend('Drupal\Core\Database\Query\PagerSelectExtender') ->limit($comments_per_page); if ($pager_id) { $query->element($pager_id); } $count_query = $this->database->select('comment_field_data', 'c'); $count_query->addExpression('COUNT(*)'); $count_query ->condition('c.entity_id', $entity->id()) ->condition('c.entity_type', $entity->getEntityTypeId()) ->condition('c.field_name', $field_name) ->condition('c.default_langcode', 1) ->addTag('entity_access') ->addTag('comment_filter') ->addMetaData('base_table', 'comment') ->addMetaData('entity', $entity) ->addMetaData('field_name', $field_name); $query->setCountQuery($count_query); } if (!$this->currentUser->hasPermission('administer comments')) { $query->condition('c.status', CommentInterface::PUBLISHED); if ($comments_per_page) { $count_query->condition('c.status', CommentInterface::PUBLISHED); } } $query->orderBy('c.created', 'ASC'); $cids = $query->execute()->fetchCol(); $comments = []; if ($cids) { $comments = $this->storage->loadMultiple($cids); } return $comments; }
现在所需要做的就是将viewElements()方法更改为 使用新loadComments()方法而不是loadThread().
$comments = $this->loadComments($entity, $field_name, $mode, $comments_per_page, $this->getSetting('pager_id'));
激活模块后,我们现在可以从管理显示管理区域中选择格式化程序。这可以在启用评论的内容类型的字段管理区域中找到。
保存表单后,评论将按日期顺序排列。