Further Drupal 8.6.4 changes. Some core files were not committed before a commit...
[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    * @var \Drupal\Core\Routing\RouteMatchInterface
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' => [
196               'comment.lazy_builders:renderForm',
197               [
198                 $entity->getEntityTypeId(),
199                 $entity->id(),
200                 $field_name,
201                 $this->getFieldSetting('comment_type'),
202               ],
203             ],
204             '#create_placeholder' => TRUE,
205           ];
206         }
207       }
208
209       $elements[] = $output + [
210         '#comment_type' => $this->getFieldSetting('comment_type'),
211         '#comment_display_mode' => $this->getFieldSetting('default_mode'),
212         'comments' => [],
213         'comment_form' => [],
214       ];
215     }
216
217     return $elements;
218   }
219
220   /**
221    * {@inheritdoc}
222    */
223   public function settingsForm(array $form, FormStateInterface $form_state) {
224     $element = [];
225     $view_modes = $this->getViewModes();
226     $element['view_mode'] = [
227       '#type' => 'select',
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,
234     ];
235     $element['pager_id'] = [
236       '#type' => 'select',
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."),
241     ];
242     return $element;
243   }
244
245   /**
246    * {@inheritdoc}
247    */
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]);
255     }
256     return $summary;
257   }
258
259   /**
260    * {@inheritdoc}
261    */
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();
269         }
270       }
271     }
272     return $dependencies;
273   }
274
275   /**
276    * Provides a list of comment view modes for the configured comment type.
277    *
278    * @return array
279    *   Associative array keyed by view mode key and having the view mode label
280    *   as value.
281    */
282   protected function getViewModes() {
283     return $this->entityManager->getViewModeOptionsByBundle('comment', $this->getFieldSetting('comment_type'));
284   }
285
286 }