protected function CommentStorageController::preSave

Overrides Drupal\Core\Entity\DatabaseStorageController::preSave().

Overrides DatabaseStorageController::preSave

See also

comment_int_to_alphadecimal()

comment_alphadecimal_to_int()

File

drupal/core/modules/comment/lib/Drupal/comment/CommentStorageController.php, line 71
Definition of Drupal\comment\CommentStorageController.

Class

CommentStorageController
Defines the controller class for comments.

Namespace

Drupal\comment

Code

protected function preSave(EntityInterface $comment) {
  global $user;
  if (!isset($comment->status->value)) {
    $comment->status->value = user_access('skip comment approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED;
  }

  // Make sure we have a proper bundle name.
  if (!isset($comment->node_type->value)) {
    $comment->node_type->value = 'comment_node_' . $comment->nid->entity->type;
  }
  if ($comment
    ->isNew()) {

    // Add the comment to database. This next section builds the thread field.
    // Also see the documentation for comment_view().
    if (!empty($comment->thread->value)) {

      // Allow calling code to set thread itself.
      $thread = $comment->thread->value;
    }
    else {
      if ($this->threadLock) {

        // As preSave() is protected, this can only happen when this class
        // is extended in a faulty manner.
        throw new LogicException('preSave is called again without calling postSave() or releaseThreadLock()');
      }
      if ($comment->pid->target_id == 0) {

        // This is a comment with no parent comment (depth 0): we start
        // by retrieving the maximum thread level.
        $max = db_query('SELECT MAX(thread) FROM {comment} WHERE nid = :nid', array(
          ':nid' => $comment->nid->target_id,
        ))
          ->fetchField();

        // Strip the "/" from the end of the thread.
        $max = rtrim($max, '/');

        // We need to get the value at the correct depth.
        $parts = explode('.', $max);
        $n = comment_alphadecimal_to_int($parts[0]);
        $prefix = '';
      }
      else {

        // This is a comment with a parent comment, so increase the part of
        // the thread value at the proper depth.
        // Get the parent comment:
        $parent = $comment->pid->entity;

        // Strip the "/" from the end of the parent thread.
        $parent->thread->value = (string) rtrim((string) $parent->thread->value, '/');
        $prefix = $parent->thread->value . '.';

        // Get the max value in *this* thread.
        $max = db_query("SELECT MAX(thread) FROM {comment} WHERE thread LIKE :thread AND nid = :nid", array(
          ':thread' => $parent->thread->value . '.%',
          ':nid' => $comment->nid->target_id,
        ))
          ->fetchField();
        if ($max == '') {

          // First child of this parent. As the other two cases do an
          // increment of the thread number before creating the thread
          // string set this to -1 so it requires an increment too.
          $n = -1;
        }
        else {

          // Strip the "/" at the end of the thread.
          $max = rtrim($max, '/');

          // Get the value at the correct depth.
          $parts = explode('.', $max);
          $parent_depth = count(explode('.', $parent->thread->value));
          $n = comment_alphadecimal_to_int($parts[$parent_depth]);
        }
      }

      // Finally, build the thread field for this new comment. To avoid
      // race conditions, get a lock on the thread. If aother process already
      // has the lock, just move to the next integer.
      do {
        $thread = $prefix . comment_int_to_alphadecimal(++$n) . '/';
      } while (!lock()
        ->acquire("comment:{$comment->nid->target_id}:{$thread}"));
      $this->threadLock = $thread;
    }
    if (empty($comment->created->value)) {
      $comment->created->value = REQUEST_TIME;
    }
    if (empty($comment->changed->value)) {
      $comment->changed->value = $comment->created->value;
    }

    // We test the value with '===' because we need to modify anonymous
    // users as well.
    if ($comment->uid->target_id === $user->uid && $user->uid) {
      $comment->name->value = $user->name;
    }

    // Add the values which aren't passed into the function.
    $comment->thread->value = $thread;
    $comment->hostname->value = \Drupal::request()
      ->getClientIP();
  }
}