Verified Commit 78cbebb1 authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #2614720 by quietone, roderik, Dylan Donkersgoed, ofry, Deepak Goyal,...

Issue #2614720 by quietone, roderik, Dylan Donkersgoed, ofry, Deepak Goyal, samiullah, jonathanshaw, catch, benjifisher, larowlan, Ruedische, Rewted, KlemenDEV, abramm, dmytro-aragorn, ao2, HiMyNameIsSeb, dionsj, mgp_novicell, xjm, vadim.hirbu, scalas89, hchonov, mayurjadhav, nplowman, rollins, paranojik: Fatal errors while loading/building orphaned comments
parent 6fdd091c
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -694,9 +694,8 @@ function template_preprocess_comment(&$variables) {

  $variables['submitted'] = t('Submitted by @username on @datetime', ['@username' => $variables['author'], '@datetime' => $variables['created']]);

  if ($comment->hasParentComment()) {
  if ($comment_parent = $comment->getParentComment()) {
    // Fetch and store the parent comment information for use in templates.
    $comment_parent = $comment->getParentComment();
    $account_parent = $comment_parent->getOwner();
    $variables['parent_comment'] = $comment_parent;
    $username = [
+3 −3
Original line number Diff line number Diff line
@@ -144,9 +144,9 @@ public function renderLinks($comment_entity_id, $view_mode, $langcode, $is_in_pr
    if (!$is_in_preview) {
      /** @var \Drupal\comment\CommentInterface $entity */
      $entity = $this->entityTypeManager->getStorage('comment')->load($comment_entity_id);
      $commented_entity = $entity->getCommentedEntity();

      if ($commented_entity = $entity->getCommentedEntity()) {
        $links['comment'] = $this->buildLinks($entity, $commented_entity);
      }

      // Allow other modules to alter the comment links.
      $hook_context = [
+10 −6
Original line number Diff line number Diff line
@@ -80,8 +80,10 @@ protected function getBuildDefaults(EntityInterface $entity, $view_mode) {

    /** @var \Drupal\comment\CommentInterface $entity */
    // Store a threading field setting to use later in self::buildComponents().
    $build['#comment_threaded'] = $entity->getCommentedEntity()
      ->getFieldDefinition($entity->getFieldName())
    $commented_entity = $entity->getCommentedEntity();
    $build['#comment_threaded'] =
      is_null($commented_entity)
      || $commented_entity->getFieldDefinition($entity->getFieldName())
        ->getSetting('default_mode') === CommentManagerInterface::COMMENT_MODE_THREADED;
    // If threading is enabled, don't render cache individual comments, but do
    // keep the cacheability metadata, so it can bubble up.
@@ -140,10 +142,12 @@ public function buildComponents(array &$build, array $entities, array $displays,

      // Commented entities already loaded after self::getBuildDefaults().
      $commented_entity = $entity->getCommentedEntity();
      // Set defaults if the commented_entity does not exist.
      $bundle = $commented_entity ? $commented_entity->bundle() : '';
      $is_node = $commented_entity ? $commented_entity->getEntityTypeId() === 'node' : NULL;

      $build[$id]['#entity'] = $entity;
      $build[$id]['#theme'] = 'comment__' . $entity->getFieldName() . '__' . $commented_entity->bundle();

      $build[$id]['#theme'] = 'comment__' . $entity->getFieldName() . '__' . $bundle;
      $display = $displays[$entity->bundle()];
      if ($display->getComponent('links')) {
        $build[$id]['links'] = [
@@ -164,7 +168,7 @@ public function buildComponents(array &$build, array $entities, array $displays,
        $build[$id]['#attached'] = [];
      }
      $build[$id]['#attached']['library'][] = 'comment/drupal.comment-by-viewer';
      if ($attach_history && $commented_entity->getEntityTypeId() === 'node') {
      if ($attach_history && $is_node) {
        $build[$id]['#attached']['library'][] = 'comment/drupal.comment-new-indicator';

        // Embed the metadata for the comment "new" indicators on this node.
+2 −1
Original line number Diff line number Diff line
@@ -404,7 +404,8 @@ public function setSubject($subject) {
   * {@inheritdoc}
   */
  public function getAuthorName() {
    if ($this->get('uid')->target_id) {
    // If their is a valid user id and the user entity exists return the label.
    if ($this->get('uid')->target_id && $this->get('uid')->entity) {
      return $this->get('uid')->entity->label();
    }
    return $this->get('name')->value ?: \Drupal::config('user.settings')->get('anonymous');
+134 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\comment\Kernel;

use Drupal\Core\Datetime\Entity\DateFormat;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\Tests\EntityViewTrait;
use Drupal\field\Entity\FieldStorageConfig;

/**
 * Tests loading and rendering orphan comments.
 *
 * @group comment
 */
class CommentOrphanTest extends EntityKernelTestBase {

  use EntityViewTrait;

  /**
   * {@inheritdoc}
   */
  public static $modules = ['comment', 'node'];

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();
    $this->installEntitySchema('date_format');
    $this->installEntitySchema('comment');
    $this->installSchema('comment', ['comment_entity_statistics']);
  }

  /**
   * Test loading/deleting/rendering orphaned comments.
   *
   * @dataProvider providerTestOrphan
   */
  public function testOrphan($property) {

    DateFormat::create([
      'id' => 'fallback',
      'label' => 'Fallback',
      'pattern' => 'Y-m-d',
    ])->save();

    $comment_storage = $this->entityTypeManager->getStorage('comment');
    $node_storage = $this->entityTypeManager->getStorage('node');

    // Create a page node type.
    $this->entityTypeManager->getStorage('node_type')->create([
      'type' => 'page',
      'name' => 'page',
    ])->save();

    $node = $node_storage->create([
      'type' => 'page',
      'title' => 'test',
    ]);
    $node->save();

    // Create comment field.
    $this->entityTypeManager->getStorage('field_storage_config')->create([
      'type' => 'text_long',
      'entity_type' => 'node',
      'field_name' => 'comment',
    ])->save();

    // Add comment field to page content.
    $this->entityTypeManager->getStorage('field_config')->create([
      'field_storage' => FieldStorageConfig::loadByName('node', 'comment'),
      'entity_type' => 'node',
      'bundle' => 'page',
      'label' => 'Comment',
    ])->save();

    // Make two comments
    $comment1 = $comment_storage->create([
      'field_name' => 'comment',
      'comment_body' => 'test',
      'entity_id' => $node->id(),
      'entity_type' => 'node',
      'comment_type' => 'default',
    ])->save();

    $comment_storage->create([
      'field_name' => 'comment',
      'comment_body' => 'test',
      'entity_id' => $node->id(),
      'entity_type' => 'node',
      'comment_type' => 'default',
      'pid' => $comment1,
    ])->save();

    // Render the comments.
    $renderer = \Drupal::service('renderer');
    $comments = $comment_storage->loadMultiple();
    foreach ($comments as $comment) {
      $built = $this->buildEntityView($comment, 'full', NULL);
      $renderer->renderPlain($built);
    }

    // Make comment 2 an orphan by setting the property to an invalid value.
    \Drupal::database()->update('comment_field_data')
      ->fields([$property => 10])
      ->condition('cid', 2)
      ->execute();
    $comment_storage->resetCache();
    $node_storage->resetCache();

    // Render the comments with an orphan comment.
    $comments = $comment_storage->loadMultiple();
    foreach ($comments as $comment) {
      $built = $this->buildEntityView($comment, 'full', NULL);
      $renderer->renderPlain($built);
    }

    $node = $node_storage->load($node->id());
    $built = $this->buildEntityView($node, 'full', NULL);
    $renderer->renderPlain($built);
  }

  /**
   * Provides test data for testOrphan.
   */
  public function providerTestOrphan() {
    return [
      ['entity_id'],
      ['uid'],
      ['pid'],
    ];
  }

}