Version 1
[yaffs-website] / web / core / modules / comment / src / Plugin / Field / FieldFormatter / CommentDefaultFormatter.php
1 <?php
2
3 namespace Drupal\comment\Plugin\Field\FieldFormatter;
4
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;
17
18 /**
19  * Provides a default comment formatter.
20  *
21  * @FieldFormatter(
22  *   id = "comment_default",
23  *   module = "comment",
24  *   label = @Translation("Comment list"),
25  *   field_types = {
26  *     "comment"
27  *   },
28  *   quickedit = {
29  *     "editor" = "disabled"
30  *   }
31  * )
32  */
33 class CommentDefaultFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
34
35   /**
36    * {@inheritdoc}
37    */
38   public static function defaultSettings() {
39     return [
40       'view_mode' => 'default',
41       'pager_id' => 0,
42     ] + parent::defaultSettings();
43   }
44
45   /**
46    * The comment storage.
47    *
48    * @var \Drupal\comment\CommentStorageInterface
49    */
50   protected $storage;
51
52   /**
53    * The current user.
54    *
55    * @var \Drupal\Core\Session\AccountInterface
56    */
57   protected $currentUser;
58
59   /**
60    * The comment render controller.
61    *
62    * @var \Drupal\Core\Entity\EntityViewBuilderInterface
63    */
64   protected $viewBuilder;
65
66   /**
67    * The entity manager.
68    *
69    * @var \Drupal\Core\Entity\EntityManagerInterface
70    */
71   protected $entityManager;
72
73   /**
74    * The entity form builder.
75    *
76    * @var \Drupal\Core\Entity\EntityFormBuilderInterface
77    */
78   protected $entityFormBuilder;
79
80   /**
81    * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
82    */
83   protected $routeMatch;
84
85   /**
86    * {@inheritdoc}
87    */
88   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
89     return new static(
90       $plugin_id,
91       $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')
101     );
102   }
103
104   /**
105    * Constructs a new CommentDefaultFormatter.
106    *
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
118    *   The view mode.
119    * @param array $third_party_settings
120    *   Third party settings.
121    * @param \Drupal\Core\Session\AccountInterface $current_user
122    *   The current user.
123    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
124    *   The 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.
129    */
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;
138   }
139
140   /**
141    * {@inheritdoc}
142    */
143   public function viewElements(FieldItemListInterface $items, $langcode) {
144     $elements = [];
145     $output = [];
146
147     $field_name = $this->fieldDefinition->getName();
148     $entity = $items->getEntity();
149
150     $status = $items->status;
151
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();
158
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'] = [];
166
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'));
171           if ($comments) {
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');
182             }
183             $output['comments'] += $build;
184           }
185         }
186       }
187
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'] = [
195             '#lazy_builder' => ['comment.lazy_builders:renderForm', [
196               $entity->getEntityTypeId(),
197               $entity->id(),
198               $field_name,
199               $this->getFieldSetting('comment_type'),
200             ]],
201             '#create_placeholder' => TRUE,
202           ];
203         }
204       }
205
206       $elements[] = $output + [
207         '#comment_type' => $this->getFieldSetting('comment_type'),
208         '#comment_display_mode' => $this->getFieldSetting('default_mode'),
209         'comments' => [],
210         'comment_form' => [],
211       ];
212     }
213
214     return $elements;
215   }
216
217   /**
218    * {@inheritdoc}
219    */
220   public function settingsForm(array $form, FormStateInterface $form_state) {
221     $element = [];
222     $view_modes = $this->getViewModes();
223     $element['view_mode'] = [
224       '#type' => 'select',
225       '#title' => $this->t('Comments view mode'),
226       '#description' => $this->t('Select the view mode used to show the list of comments.'),
227       '#default_value' => $this->getSetting('view_mode'),
228       '#options' => $view_modes,
229       // Only show the select element when there are more than one options.
230       '#access' => count($view_modes) > 1,
231     ];
232     $element['pager_id'] = [
233       '#type' => 'select',
234       '#title' => $this->t('Pager ID'),
235       '#options' => range(0, 10),
236       '#default_value' => $this->getSetting('pager_id'),
237       '#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."),
238     ];
239     return $element;
240   }
241
242   /**
243    * {@inheritdoc}
244    */
245   public function settingsSummary() {
246     $view_mode = $this->getSetting('view_mode');
247     $view_modes = $this->getViewModes();
248     $view_mode_label = isset($view_modes[$view_mode]) ? $view_modes[$view_mode] : 'default';
249     $summary = [$this->t('Comment view mode: @mode', ['@mode' => $view_mode_label])];
250     if ($pager_id = $this->getSetting('pager_id')) {
251       $summary[] = $this->t('Pager ID: @id', ['@id' => $pager_id]);
252     }
253     return $summary;
254   }
255
256   /**
257    * {@inheritdoc}
258    */
259   public function calculateDependencies() {
260     $dependencies = parent::calculateDependencies();
261     if ($mode = $this->getSetting('view_mode')) {
262       if ($bundle = $this->getFieldSetting('comment_type')) {
263         /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */
264         if ($display = EntityViewDisplay::load("comment.$bundle.$mode")) {
265           $dependencies[$display->getConfigDependencyKey()][] = $display->getConfigDependencyName();
266         }
267       }
268     }
269     return $dependencies;
270   }
271
272   /**
273    * Provides a list of comment view modes for the configured comment type.
274    *
275    * @return array
276    *   Associative array keyed by view mode key and having the view mode label
277    *   as value.
278    */
279   protected function getViewModes() {
280     return $this->entityManager->getViewModeOptionsByBundle('comment', $this->getFieldSetting('comment_type'));
281   }
282
283 }