'integer', 'article_id' => 'integer', 'user_id' => 'integer', 'parent_id' => 'integer', 'legacy_user_id' => 'integer', 'legacy_posted_at' => 'datetime', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime', ]; public function article(): BelongsTo { return $this->belongsTo(NewsArticle::class, 'article_id'); } public function user(): BelongsTo { return $this->belongsTo(User::class); } public function parent(): BelongsTo { return $this->belongsTo(self::class, 'parent_id'); } public function replies(): HasMany { return $this->hasMany(self::class, 'parent_id')->orderBy('created_at')->orderBy('id'); } public function visibleReplies(): HasMany { return $this->hasMany(self::class, 'parent_id') ->where('status', 'visible') ->orderBy('created_at') ->orderBy('id') ->with(['user.profile', 'visibleReplies']); } public function reactions(): HasMany { return $this->hasMany(NewsArticleCommentReaction::class, 'comment_id'); } public function getDisplayHtml(): string { $rendered = is_string($this->rendered_body) ? trim($this->rendered_body) : ''; $body = (string) ($this->body ?? ''); if ($rendered === '') { $rendered = $body !== '' ? ContentSanitizer::render($body) : nl2br(e($body)); } return ContentSanitizer::sanitizeRenderedHtml($rendered, $this->authorCanPublishLinks()); } private function authorCanPublishLinks(): bool { $level = (int) ($this->user?->level ?? 1); $rank = strtolower((string) ($this->user?->rank ?? 'newbie')); return $level > 1 && $rank !== 'newbie'; } }