You are here

public function Comment::preSave in Drupal 10

Same name and namespace in other branches
  1. 8 core/modules/comment/src/Entity/Comment.php \Drupal\comment\Entity\Comment::preSave()
  2. 9 core/modules/comment/src/Entity/Comment.php \Drupal\comment\Entity\Comment::preSave()

File

core/modules/comment/src/Entity/Comment.php, line 87

Class

Comment
Defines the comment entity class.

Namespace

Drupal\comment\Entity

Code

public function preSave(EntityStorageInterface $storage) {
  parent::preSave($storage);
  if ($this
    ->isNew()) {

    // Add the comment to database. This next section builds the thread field.
    // @see \Drupal\comment\CommentViewBuilder::buildComponents()
    $thread = $this
      ->getThread();
    if (empty($thread)) {
      if ($this->threadLock) {

        // Thread lock was not released after being set previously.
        // This suggests there's a bug in code using this class.
        throw new \LogicException('preSave() is called again without calling postSave() or releaseThreadLock()');
      }
      if (!$this
        ->hasParentComment()) {

        // This is a comment with no parent comment (depth 0): we start
        // by retrieving the maximum thread level.
        $max = $storage
          ->getMaxThread($this);

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

        // We need to get the value at the correct depth.
        $parts = explode('.', $max);
        $n = Number::alphadecimalToInt($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 = $this
          ->getParentComment();

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

        // Get the max value in *this* thread.
        $max = $storage
          ->getMaxThreadPerThread($this);
        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
            ->getThread()));
          $n = Number::alphadecimalToInt($parts[$parent_depth]);
        }
      }

      // Finally, build the thread field for this new comment. To avoid
      // race conditions, get a lock on the thread. If another process already
      // has the lock, just move to the next integer.
      do {
        $thread = $prefix . Number::intToAlphadecimal(++$n) . '/';
        $lock_name = "comment:{$this->getCommentedEntityId()}:{$thread}";
      } while (!\Drupal::lock()
        ->acquire($lock_name));
      $this->threadLock = $lock_name;
    }
    $this
      ->setThread($thread);
  }

  // The entity fields for name and mail have no meaning if the user is not
  // Anonymous. Set them to NULL to make it clearer that they are not used.
  // For anonymous users see \Drupal\comment\CommentForm::form() for mail,
  // and \Drupal\comment\CommentForm::buildEntity() for name setting.
  if (!$this
    ->getOwner()
    ->isAnonymous()) {
    $this
      ->set('name', NULL);
    $this
      ->set('mail', NULL);
  }
}