288 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			288 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @file
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								use Drupal\comment\CommentInterface;
							 | 
						||
| 
								 | 
							
								use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Form\FormStateInterface;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Render\Element;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Link;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Url;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * The time cutoff for comments marked as read for entity types other node.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Comments changed before this time are always marked as read.
							 | 
						||
| 
								 | 
							
								 * Comments changed after this time may be marked new, updated, or read,
							 | 
						||
| 
								 | 
							
								 * depending on their state for the current user. Defaults to 30 days ago.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @todo Remove when https://www.drupal.org/node/2006632 lands.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								define('COMMENT_NEW_LIMIT', ((int) $_SERVER['REQUEST_TIME']) - 30 * 24 * 60 * 60);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Entity URI callback.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function comment_uri(CommentInterface $comment) {
							 | 
						||
| 
								 | 
							
								  return new Url(
							 | 
						||
| 
								 | 
							
								    'entity.comment.canonical',
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								      'comment' => $comment->id(),
							 | 
						||
| 
								 | 
							
								    ],
							 | 
						||
| 
								 | 
							
								    ['fragment' => 'comment-' . $comment->id()]
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Determines if an entity type is using an integer-based ID definition.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param string $entity_type_id
							 | 
						||
| 
								 | 
							
								 *   The ID the represents the entity type.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return bool
							 | 
						||
| 
								 | 
							
								 *   Returns TRUE if the entity type has an integer-based ID definition and
							 | 
						||
| 
								 | 
							
								 *   FALSE otherwise.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function _comment_entity_uses_integer_id($entity_type_id) {
							 | 
						||
| 
								 | 
							
								  $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
							 | 
						||
| 
								 | 
							
								  $entity_type_id_key = $entity_type->getKey('id');
							 | 
						||
| 
								 | 
							
								  if ($entity_type_id_key === FALSE) {
							 | 
						||
| 
								 | 
							
								    return FALSE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  $field_definitions = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions($entity_type->id());
							 | 
						||
| 
								 | 
							
								  $entity_type_id_definition = $field_definitions[$entity_type_id_key];
							 | 
						||
| 
								 | 
							
								  return $entity_type_id_definition->getType() === 'integer';
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Generates a comment preview.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param \Drupal\comment\CommentInterface $comment
							 | 
						||
| 
								 | 
							
								 *   The comment entity to preview.
							 | 
						||
| 
								 | 
							
								 * @param Drupal\Core\Form\FormStateInterface $form_state
							 | 
						||
| 
								 | 
							
								 *   The current state of the form.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return array
							 | 
						||
| 
								 | 
							
								 *   An array as expected by \Drupal\Core\Render\RendererInterface::render().
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function comment_preview(CommentInterface $comment, FormStateInterface $form_state): array {
							 | 
						||
| 
								 | 
							
								  $preview_build = [];
							 | 
						||
| 
								 | 
							
								  $entity = $comment->getCommentedEntity();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!$form_state->getErrors()) {
							 | 
						||
| 
								 | 
							
								    $comment->in_preview = TRUE;
							 | 
						||
| 
								 | 
							
								    $comment_build = \Drupal::entityTypeManager()->getViewBuilder('comment')->view($comment);
							 | 
						||
| 
								 | 
							
								    $comment_build['#weight'] = -100;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $preview_build['comment_preview'] = $comment_build;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ($comment->hasParentComment()) {
							 | 
						||
| 
								 | 
							
								    $build = [];
							 | 
						||
| 
								 | 
							
								    $parent = $comment->getParentComment();
							 | 
						||
| 
								 | 
							
								    if ($parent && $parent->isPublished()) {
							 | 
						||
| 
								 | 
							
								      $build = \Drupal::entityTypeManager()->getViewBuilder('comment')->view($parent);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else {
							 | 
						||
| 
								 | 
							
								    // The comment field output includes rendering the parent entity of the
							 | 
						||
| 
								 | 
							
								    // thread to which the comment is a reply. The rendered entity output
							 | 
						||
| 
								 | 
							
								    // includes the comment reply form, which contains the comment preview and
							 | 
						||
| 
								 | 
							
								    // therefore the rendered parent entity. This results in an infinite loop of
							 | 
						||
| 
								 | 
							
								    // parent entity output rendering the comment form and the comment form
							 | 
						||
| 
								 | 
							
								    // rendering the parent entity. To prevent this infinite loop we temporarily
							 | 
						||
| 
								 | 
							
								    // set the value of the comment field on a clone of the entity to hidden
							 | 
						||
| 
								 | 
							
								    // before calling the entity view builder. That way when the output of
							 | 
						||
| 
								 | 
							
								    // the commented entity is rendered, it excludes the comment field output.
							 | 
						||
| 
								 | 
							
								    $field_name = $comment->getFieldName();
							 | 
						||
| 
								 | 
							
								    $entity = clone $entity;
							 | 
						||
| 
								 | 
							
								    $entity->$field_name->status = CommentItemInterface::HIDDEN;
							 | 
						||
| 
								 | 
							
								    $build = \Drupal::entityTypeManager()
							 | 
						||
| 
								 | 
							
								      ->getViewBuilder($entity->getEntityTypeId())
							 | 
						||
| 
								 | 
							
								      ->view($entity, 'full');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  $preview_build['comment_output_below'] = $build;
							 | 
						||
| 
								 | 
							
								  $preview_build['comment_output_below']['#weight'] = 200;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return $preview_build;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Prepares variables for comment templates.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * By default this function performs special preprocessing of some base fields
							 | 
						||
| 
								 | 
							
								 * so they are available as variables in the template. For example 'subject'
							 | 
						||
| 
								 | 
							
								 * appears as 'title'. This preprocessing is skipped if:
							 | 
						||
| 
								 | 
							
								 * - a module makes the field's display configurable via the field UI by means
							 | 
						||
| 
								 | 
							
								 *   of BaseFieldDefinition::setDisplayConfigurable()
							 | 
						||
| 
								 | 
							
								 * - AND the additional entity type property
							 | 
						||
| 
								 | 
							
								 *   'enable_base_field_custom_preprocess_skipping' has been set using
							 | 
						||
| 
								 | 
							
								 *   hook_entity_type_build().
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Default template: comment.html.twig.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param array $variables
							 | 
						||
| 
								 | 
							
								 *   An associative array containing:
							 | 
						||
| 
								 | 
							
								 *   - elements: An associative array containing the comment and entity objects.
							 | 
						||
| 
								 | 
							
								 *     Array keys: #comment, #commented_entity.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function template_preprocess_comment(&$variables): void {
							 | 
						||
| 
								 | 
							
								  /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
							 | 
						||
| 
								 | 
							
								  $date_formatter = \Drupal::service('date.formatter');
							 | 
						||
| 
								 | 
							
								  /** @var \Drupal\comment\CommentInterface $comment */
							 | 
						||
| 
								 | 
							
								  $comment = $variables['elements']['#comment'];
							 | 
						||
| 
								 | 
							
								  $commented_entity = $comment->getCommentedEntity();
							 | 
						||
| 
								 | 
							
								  $variables['comment'] = $comment;
							 | 
						||
| 
								 | 
							
								  $variables['commented_entity'] = $commented_entity;
							 | 
						||
| 
								 | 
							
								  $variables['threaded'] = $variables['elements']['#comment_threaded'];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  $skip_custom_preprocessing = $comment->getEntityType()->get('enable_base_field_custom_preprocess_skipping');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Make created, uid, pid and subject fields available separately. Skip this
							 | 
						||
| 
								 | 
							
								  // custom preprocessing if the field display is configurable and skipping has
							 | 
						||
| 
								 | 
							
								  // been enabled.
							 | 
						||
| 
								 | 
							
								  // @todo https://www.drupal.org/project/drupal/issues/3015623
							 | 
						||
| 
								 | 
							
								  //   Eventually delete this code and matching template lines. Using
							 | 
						||
| 
								 | 
							
								  //   $variables['content'] is more flexible and consistent.
							 | 
						||
| 
								 | 
							
								  $submitted_configurable = $comment->getFieldDefinition('created')->isDisplayConfigurable('view') || $comment->getFieldDefinition('uid')->isDisplayConfigurable('view');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!$skip_custom_preprocessing || !$submitted_configurable) {
							 | 
						||
| 
								 | 
							
								    $account = $comment->getOwner();
							 | 
						||
| 
								 | 
							
								    $username = [
							 | 
						||
| 
								 | 
							
								      '#theme' => 'username',
							 | 
						||
| 
								 | 
							
								      '#account' => $account,
							 | 
						||
| 
								 | 
							
								    ];
							 | 
						||
| 
								 | 
							
								    $variables['author'] = \Drupal::service('renderer')->render($username);
							 | 
						||
| 
								 | 
							
								    $variables['author_id'] = $comment->getOwnerId();
							 | 
						||
| 
								 | 
							
								    $variables['new_indicator_timestamp'] = $comment->getChangedTime();
							 | 
						||
| 
								 | 
							
								    $variables['created'] = $date_formatter->format($comment->getCreatedTime());
							 | 
						||
| 
								 | 
							
								    // Avoid calling DateFormatterInterface::format() twice on the same
							 | 
						||
| 
								 | 
							
								    // timestamp.
							 | 
						||
| 
								 | 
							
								    if ($comment->getChangedTime() == $comment->getCreatedTime()) {
							 | 
						||
| 
								 | 
							
								      $variables['changed'] = $variables['created'];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								      $variables['changed'] = $date_formatter->format($comment->getChangedTime());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (theme_get_setting('features.comment_user_picture')) {
							 | 
						||
| 
								 | 
							
								      // To change user picture settings (for instance, image style), edit the
							 | 
						||
| 
								 | 
							
								      // 'compact' view mode on the User entity.
							 | 
						||
| 
								 | 
							
								      $variables['user_picture'] = \Drupal::entityTypeManager()
							 | 
						||
| 
								 | 
							
								        ->getViewBuilder('user')
							 | 
						||
| 
								 | 
							
								        ->view($account, 'compact');
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								      $variables['user_picture'] = [];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $variables['submitted'] = t('Submitted by @username on @datetime', ['@username' => $variables['author'], '@datetime' => $variables['created']]);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (isset($comment->in_preview)) {
							 | 
						||
| 
								 | 
							
								    $variables['permalink'] = Link::fromTextAndUrl(t('Permalink'), Url::fromRoute('<front>'))->toString();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else {
							 | 
						||
| 
								 | 
							
								    $variables['permalink'] = Link::fromTextAndUrl(t('Permalink'), $comment->permalink())->toString();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (($comment_parent = $comment->getParentComment()) && (!$skip_custom_preprocessing || !$comment->getFieldDefinition('pid')->isDisplayConfigurable('view'))) {
							 | 
						||
| 
								 | 
							
								    // Fetch and store the parent comment information for use in templates.
							 | 
						||
| 
								 | 
							
								    $account_parent = $comment_parent->getOwner();
							 | 
						||
| 
								 | 
							
								    $variables['parent_comment'] = $comment_parent;
							 | 
						||
| 
								 | 
							
								    $username = [
							 | 
						||
| 
								 | 
							
								      '#theme' => 'username',
							 | 
						||
| 
								 | 
							
								      '#account' => $account_parent,
							 | 
						||
| 
								 | 
							
								    ];
							 | 
						||
| 
								 | 
							
								    $variables['parent_author'] = \Drupal::service('renderer')->render($username);
							 | 
						||
| 
								 | 
							
								    $variables['parent_created'] = $date_formatter->format($comment_parent->getCreatedTime());
							 | 
						||
| 
								 | 
							
								    // Avoid calling DateFormatterInterface::format() twice on same timestamp.
							 | 
						||
| 
								 | 
							
								    if ($comment_parent->getChangedTime() == $comment_parent->getCreatedTime()) {
							 | 
						||
| 
								 | 
							
								      $variables['parent_changed'] = $variables['parent_created'];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								      $variables['parent_changed'] = $date_formatter->format($comment_parent->getChangedTime());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    $permalink_uri_parent = $comment_parent->permalink();
							 | 
						||
| 
								 | 
							
								    $attributes = $permalink_uri_parent->getOption('attributes') ?: [];
							 | 
						||
| 
								 | 
							
								    $attributes += ['class' => ['permalink'], 'rel' => 'bookmark'];
							 | 
						||
| 
								 | 
							
								    $permalink_uri_parent->setOption('attributes', $attributes);
							 | 
						||
| 
								 | 
							
								    $variables['parent_title'] = Link::fromTextAndUrl($comment_parent->getSubject(), $permalink_uri_parent)->toString();
							 | 
						||
| 
								 | 
							
								    $variables['parent_permalink'] = Link::fromTextAndUrl(t('Parent permalink'), $permalink_uri_parent)->toString();
							 | 
						||
| 
								 | 
							
								    $variables['parent'] = t('In reply to @parent_title by @parent_username',
							 | 
						||
| 
								 | 
							
								        ['@parent_username' => $variables['parent_author'], '@parent_title' => $variables['parent_title']]);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else {
							 | 
						||
| 
								 | 
							
								    $variables['parent_comment'] = '';
							 | 
						||
| 
								 | 
							
								    $variables['parent_author'] = '';
							 | 
						||
| 
								 | 
							
								    $variables['parent_created'] = '';
							 | 
						||
| 
								 | 
							
								    $variables['parent_changed'] = '';
							 | 
						||
| 
								 | 
							
								    $variables['parent_title'] = '';
							 | 
						||
| 
								 | 
							
								    $variables['parent_permalink'] = '';
							 | 
						||
| 
								 | 
							
								    $variables['parent'] = '';
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!$skip_custom_preprocessing || !$comment->getFieldDefinition('subject')->isDisplayConfigurable('view')) {
							 | 
						||
| 
								 | 
							
								    if (isset($comment->in_preview)) {
							 | 
						||
| 
								 | 
							
								      $variables['title'] = Link::fromTextAndUrl($comment->getSubject(), Url::fromRoute('<front>'))->toString();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								      $uri = $comment->permalink();
							 | 
						||
| 
								 | 
							
								      $attributes = $uri->getOption('attributes') ?: [];
							 | 
						||
| 
								 | 
							
								      $attributes += ['class' => ['permalink'], 'rel' => 'bookmark'];
							 | 
						||
| 
								 | 
							
								      $uri->setOption('attributes', $attributes);
							 | 
						||
| 
								 | 
							
								      $variables['title'] = Link::fromTextAndUrl($comment->getSubject(), $uri)->toString();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Helpful $content variable for templates.
							 | 
						||
| 
								 | 
							
								  foreach (Element::children($variables['elements']) as $key) {
							 | 
						||
| 
								 | 
							
								    $variables['content'][$key] = $variables['elements'][$key];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Set status to a string representation of comment->status.
							 | 
						||
| 
								 | 
							
								  if (isset($comment->in_preview)) {
							 | 
						||
| 
								 | 
							
								    $variables['status'] = 'preview';
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else {
							 | 
						||
| 
								 | 
							
								    $variables['status'] = $comment->isPublished() ? 'published' : 'unpublished';
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Add comment author user ID. Necessary for the comment-by-viewer library.
							 | 
						||
| 
								 | 
							
								  $variables['attributes']['data-comment-user-id'] = $comment->getOwnerId();
							 | 
						||
| 
								 | 
							
								  // Add anchor for each comment.
							 | 
						||
| 
								 | 
							
								  $variables['attributes']['id'] = 'comment-' . $comment->id();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Prepares variables for comment field templates.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Default template: field--comment.html.twig.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param array $variables
							 | 
						||
| 
								 | 
							
								 *   An associative array containing:
							 | 
						||
| 
								 | 
							
								 *   - element: An associative array containing render arrays for the list of
							 | 
						||
| 
								 | 
							
								 *     comments, and the comment form. Array keys: comments, comment_form.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @todo Rename to template_preprocess_field__comment() once
							 | 
						||
| 
								 | 
							
								 *   https://www.drupal.org/node/939462 is resolved.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function comment_preprocess_field(&$variables): void {
							 | 
						||
| 
								 | 
							
								  $element = $variables['element'];
							 | 
						||
| 
								 | 
							
								  if ($element['#field_type'] == 'comment') {
							 | 
						||
| 
								 | 
							
								    // Provide contextual information.
							 | 
						||
| 
								 | 
							
								    $variables['comment_display_mode'] = $element[0]['#comment_display_mode'];
							 | 
						||
| 
								 | 
							
								    $variables['comment_type'] = $element[0]['#comment_type'];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Append additional attributes from the first field item.
							 | 
						||
| 
								 | 
							
								    $variables['attributes'] += $variables['items'][0]['attributes']->storage();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Create separate variables for the comments and comment form.
							 | 
						||
| 
								 | 
							
								    $variables['comments'] = $element[0]['comments'];
							 | 
						||
| 
								 | 
							
								    $variables['comment_form'] = $element[0]['comment_form'];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |