You are here

CommentThread.php in Comment Delete 8

File

src/CommentThread.php
View source
<?php

namespace Drupal\comment_delete;

use Drupal\Component\Utility\Number;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;

/**
 * Service container for comment thread calculations.
 *
 * @package Drupal\comment_delete
 */
class CommentThread {

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $connection;

  /**
   * CommentDelete constructor.
   *
   * @param \Drupal\Core\Database\Connection $connection
   *   The database connection.
   */
  public function __construct(Connection $connection) {
    $this->connection = $connection;
  }

  /**
   * Re-thread comments attached to an entity.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The commented entity.
   */
  public function thread(EntityInterface $entity) {

    // Get all comments attached to the entity. Not using the entity manager
    // query because its quicker to query the fields directly on big threads.
    $query = $this->connection
      ->select('comment_field_data')
      ->fields('comment_field_data', [
      'cid',
      'pid',
      'created',
    ])
      ->condition('entity_type', $entity
      ->getEntityTypeId())
      ->condition('entity_id', $entity
      ->id())
      ->orderBy('created');
    $comments = $query
      ->execute()
      ->fetchAllAssoc('cid');
    array_walk($comments, function (&$item) {
      $item = (array) $item;
    });
    $tree = $this
      ->getThreadTree($comments);
    $threads = $this
      ->getThreadValues($tree);

    // Update comment threads in database table.
    foreach ($threads as $cid => $thread_string) {
      $this->connection
        ->update('comment_field_data')
        ->fields([
        'thread' => $thread_string . '/',
      ])
        ->condition('cid', $cid)
        ->execute();
    }
  }

  /**
   * Creates associative array of threaded comments.
   *
   * @param array $comments
   *   Flat array of entity comments.
   * @param int $pid
   *   Parent ID used to recursively create array.
   *
   * @return array
   *   Associative array of threaded comments.
   */
  protected function getThreadTree(array $comments, $pid = 0) {
    $branch = [];
    foreach ($comments as $comment) {
      if ($comment['pid'] == $pid) {
        $children = $this
          ->getThreadTree($comments, $comment['cid']);
        if ($children) {
          $comment['children'] = $children;
        }
        $branch[] = $comment;
      }
    }
    return $branch;
  }

  /**
   * Converts threaded comments into associative array of threads.
   *
   * @param array $tree
   *   Associative array containing comment thread tree.
   * @param string $prefix
   *   Prefix to be prepended to thread strings.
   * @param array $threads
   *   Associative array of existing thread strings.
   * @param bool $first_level
   *   Boolean indicating the first thread level.
   *
   * @return array
   *   Associative array of comment thread strings.
   */
  protected function getThreadValues(array $tree, $prefix = '', array $threads = [], $first_level = TRUE) {
    $thread = $first_level ? '01' : '00';
    uasort($tree, [
      $this,
      'sortThread',
    ]);
    foreach ($tree as $comment) {
      $string = (!empty($prefix) ? $prefix . '.' : '') . Number::intToAlphadecimal(sprintf('%02d', $thread++));
      $threads[$comment['cid']] = $string;
      if (isset($comment['children'])) {
        $children = $comment['children'];
        uasort($children, [
          $this,
          'sortThread',
        ]);
        $child_threading = $this
          ->getThreadValues($children, $string, $threads, FALSE);
        $threads += $child_threading;
      }
    }
    return $threads;
  }

  /**
   * Sorts associative array of comments by creation time.
   *
   * @param array $a
   *   The left comment.
   * @param array $b
   *   The right comment.
   *
   * @return int
   *   The sorting integer.
   */
  protected function sortThread(array $a, array $b) {
    if ($a['created'] == $b['created']) {
      return 0;
    }
    return $a['created'] < $b['created'] ? -1 : 1;
  }

}

Classes

Namesort descending Description
CommentThread Service container for comment thread calculations.