3 namespace Drupal\comment\Plugin\Field\FieldFormatter;
5 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
6 use Drupal\Core\Entity\Entity\EntityViewDisplay;
7 use Drupal\Core\Entity\EntityManagerInterface;
8 use Drupal\Core\Entity\EntityFormBuilderInterface;
9 use Drupal\Core\Field\FieldItemListInterface;
10 use Drupal\Core\Form\FormStateInterface;
11 use Drupal\Core\Session\AccountInterface;
12 use Drupal\Core\Field\FieldDefinitionInterface;
13 use Drupal\Core\Field\FormatterBase;
14 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
15 use Drupal\Core\Routing\RouteMatchInterface;
16 use Symfony\Component\DependencyInjection\ContainerInterface;
19 * Provides a default comment formatter.
22 * id = "comment_default",
24 * label = @Translation("Comment list"),
29 * "editor" = "disabled"
33 class CommentDefaultFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
38 public static function defaultSettings() {
40 'view_mode' => 'default',
42 ] + parent::defaultSettings();
46 * The comment storage.
48 * @var \Drupal\comment\CommentStorageInterface
55 * @var \Drupal\Core\Session\AccountInterface
57 protected $currentUser;
60 * The comment render controller.
62 * @var \Drupal\Core\Entity\EntityViewBuilderInterface
64 protected $viewBuilder;
69 * @var \Drupal\Core\Entity\EntityManagerInterface
71 protected $entityManager;
74 * The entity form builder.
76 * @var \Drupal\Core\Entity\EntityFormBuilderInterface
78 protected $entityFormBuilder;
81 * @var \Drupal\Core\Routing\RouteMatchInterface
83 protected $routeMatch;
88 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
92 $configuration['field_definition'],
93 $configuration['settings'],
94 $configuration['label'],
95 $configuration['view_mode'],
96 $configuration['third_party_settings'],
97 $container->get('current_user'),
98 $container->get('entity.manager'),
99 $container->get('entity.form_builder'),
100 $container->get('current_route_match')
105 * Constructs a new CommentDefaultFormatter.
107 * @param string $plugin_id
108 * The plugin_id for the formatter.
109 * @param mixed $plugin_definition
110 * The plugin implementation definition.
111 * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
112 * The definition of the field to which the formatter is associated.
113 * @param array $settings
114 * The formatter settings.
115 * @param string $label
116 * The formatter label display setting.
117 * @param string $view_mode
119 * @param array $third_party_settings
120 * Third party settings.
121 * @param \Drupal\Core\Session\AccountInterface $current_user
123 * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
125 * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entity_form_builder
126 * The entity form builder.
127 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
128 * The route match object.
130 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) {
131 parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
132 $this->viewBuilder = $entity_manager->getViewBuilder('comment');
133 $this->storage = $entity_manager->getStorage('comment');
134 $this->currentUser = $current_user;
135 $this->entityManager = $entity_manager;
136 $this->entityFormBuilder = $entity_form_builder;
137 $this->routeMatch = $route_match;
143 public function viewElements(FieldItemListInterface $items, $langcode) {
147 $field_name = $this->fieldDefinition->getName();
148 $entity = $items->getEntity();
150 $status = $items->status;
152 if ($status != CommentItemInterface::HIDDEN && empty($entity->in_preview) &&
153 // Comments are added to the search results and search index by
154 // comment_node_update_index() instead of by this formatter, so don't
155 // return anything if the view mode is search_index or search_result.
156 !in_array($this->viewMode, ['search_result', 'search_index'])) {
157 $comment_settings = $this->getFieldSettings();
159 // Only attempt to render comments if the entity has visible comments.
160 // Unpublished comments are not included in
161 // $entity->get($field_name)->comment_count, but unpublished comments
162 // should display if the user is an administrator.
163 $elements['#cache']['contexts'][] = 'user.permissions';
164 if ($this->currentUser->hasPermission('access comments') || $this->currentUser->hasPermission('administer comments')) {
165 $output['comments'] = [];
167 if ($entity->get($field_name)->comment_count || $this->currentUser->hasPermission('administer comments')) {
168 $mode = $comment_settings['default_mode'];
169 $comments_per_page = $comment_settings['per_page'];
170 $comments = $this->storage->loadThread($entity, $field_name, $mode, $comments_per_page, $this->getSetting('pager_id'));
172 $build = $this->viewBuilder->viewMultiple($comments, $this->getSetting('view_mode'));
173 $build['pager']['#type'] = 'pager';
174 // CommentController::commentPermalink() calculates the page number
175 // where a specific comment appears and does a subrequest pointing to
176 // that page, we need to pass that subrequest route to our pager to
177 // keep the pager working.
178 $build['pager']['#route_name'] = $this->routeMatch->getRouteObject();
179 $build['pager']['#route_parameters'] = $this->routeMatch->getRawParameters()->all();
180 if ($this->getSetting('pager_id')) {
181 $build['pager']['#element'] = $this->getSetting('pager_id');
183 $output['comments'] += $build;
188 // Append comment form if the comments are open and the form is set to
189 // display below the entity. Do not show the form for the print view mode.
190 if ($status == CommentItemInterface::OPEN && $comment_settings['form_location'] == CommentItemInterface::FORM_BELOW && $this->viewMode != 'print') {
191 // Only show the add comment form if the user has permission.
192 $elements['#cache']['contexts'][] = 'user.roles';
193 if ($this->currentUser->hasPermission('post comments')) {
194 $output['comment_form'] = [
196 'comment.lazy_builders:renderForm',
198 $entity->getEntityTypeId(),
201 $this->getFieldSetting('comment_type'),
204 '#create_placeholder' => TRUE,
209 $elements[] = $output + [
210 '#comment_type' => $this->getFieldSetting('comment_type'),
211 '#comment_display_mode' => $this->getFieldSetting('default_mode'),
213 'comment_form' => [],
223 public function settingsForm(array $form, FormStateInterface $form_state) {
225 $view_modes = $this->getViewModes();
226 $element['view_mode'] = [
228 '#title' => $this->t('Comments view mode'),
229 '#description' => $this->t('Select the view mode used to show the list of comments.'),
230 '#default_value' => $this->getSetting('view_mode'),
231 '#options' => $view_modes,
232 // Only show the select element when there are more than one options.
233 '#access' => count($view_modes) > 1,
235 $element['pager_id'] = [
237 '#title' => $this->t('Pager ID'),
238 '#options' => range(0, 10),
239 '#default_value' => $this->getSetting('pager_id'),
240 '#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."),
248 public function settingsSummary() {
249 $view_mode = $this->getSetting('view_mode');
250 $view_modes = $this->getViewModes();
251 $view_mode_label = isset($view_modes[$view_mode]) ? $view_modes[$view_mode] : 'default';
252 $summary = [$this->t('Comment view mode: @mode', ['@mode' => $view_mode_label])];
253 if ($pager_id = $this->getSetting('pager_id')) {
254 $summary[] = $this->t('Pager ID: @id', ['@id' => $pager_id]);
262 public function calculateDependencies() {
263 $dependencies = parent::calculateDependencies();
264 if ($mode = $this->getSetting('view_mode')) {
265 if ($bundle = $this->getFieldSetting('comment_type')) {
266 /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */
267 if ($display = EntityViewDisplay::load("comment.$bundle.$mode")) {
268 $dependencies[$display->getConfigDependencyKey()][] = $display->getConfigDependencyName();
272 return $dependencies;
276 * Provides a list of comment view modes for the configured comment type.
279 * Associative array keyed by view mode key and having the view mode label
282 protected function getViewModes() {
283 return $this->entityManager->getViewModeOptionsByBundle('comment', $this->getFieldSetting('comment_type'));