3 namespace BookStack\Activity\Tools;
5 use BookStack\Activity\Models\Comment;
6 use BookStack\Entities\Models\Page;
7 use BookStack\Permissions\Permission;
12 * The built nested tree structure array.
13 * @var CommentTreeNode[]
15 protected array $tree;
18 * A linear array of loaded comments.
21 protected array $comments;
23 public function __construct(
26 $this->comments = $this->loadComments();
27 $this->tree = $this->createTree($this->comments);
30 public function enabled(): bool
32 return !setting('app-disable-comments');
35 public function empty(): bool
37 return count($this->getActive()) === 0;
40 public function count(): int
42 return count($this->comments);
45 public function getActive(): array
47 return array_values(array_filter($this->tree, fn (CommentTreeNode $node) => !$node->comment->archived));
50 public function activeThreadCount(): int
52 return count($this->getActive());
55 public function getArchived(): array
57 return array_values(array_filter($this->tree, fn (CommentTreeNode $node) => $node->comment->archived));
60 public function archivedThreadCount(): int
62 return count($this->getArchived());
65 public function getCommentNodeForId(int $commentId): ?CommentTreeNode
67 foreach ($this->tree as $node) {
68 if ($node->comment->id === $commentId) {
76 public function canUpdateAny(): bool
78 foreach ($this->comments as $comment) {
79 if (userCan(Permission::CommentUpdate, $comment)) {
87 public function loadVisibleHtml(): void
89 foreach ($this->comments as $comment) {
90 $comment->setAttribute('html', $comment->safeHtml());
91 $comment->makeVisible('html');
96 * @param Comment[] $comments
97 * @return CommentTreeNode[]
99 protected function createTree(array $comments): array
102 foreach ($comments as $comment) {
103 $byId[$comment->local_id] = $comment;
107 foreach ($comments as $comment) {
108 $parent = $comment->parent_id;
109 if (is_null($parent) || !isset($byId[$parent])) {
113 if (!isset($childMap[$parent])) {
114 $childMap[$parent] = [];
116 $childMap[$parent][] = $comment->local_id;
120 foreach ($childMap[0] ?? [] as $childId) {
121 $tree[] = $this->createTreeNodeForId($childId, 0, $byId, $childMap);
127 protected function createTreeNodeForId(int $id, int $depth, array &$byId, array &$childMap): CommentTreeNode
129 $childIds = $childMap[$id] ?? [];
132 foreach ($childIds as $childId) {
133 $children[] = $this->createTreeNodeForId($childId, $depth + 1, $byId, $childMap);
136 return new CommentTreeNode($byId[$id], $depth, $children);
142 protected function loadComments(): array
144 if (!$this->enabled()) {
148 return $this->page->comments()