Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.61% covered (success)
96.61%
57 / 59
80.00% covered (success)
80.00%
8 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Comments
96.61% covered (success)
96.61%
57 / 59
80.00% covered (success)
80.00%
8 / 10
16
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCommentsData
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 getCommentsDataPaginated
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 countComments
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 create
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 delete
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNumberOfComments
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getNumberOfCommentsByCategory
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getAllComments
93.75% covered (success)
93.75%
15 / 16
0.00% covered (danger)
0.00%
0 / 1
3.00
 isCommentAllowed
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * The main Comment class.
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public License,
7 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
8 * obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * @package   phpMyFAQ
11 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
12 * @copyright 2006-2026 phpMyFAQ Team
13 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
14 * @link      https://www.phpmyfaq.de
15 * @since     2006-07-23
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ;
21
22use DateTimeInterface;
23use phpMyFAQ\Comment\CommentsRepository;
24use phpMyFAQ\Entity\Comment;
25use phpMyFAQ\Entity\CommentType;
26
27/**
28 * Class Comments
29 * @package phpMyFAQ
30 */
31class Comments
32{
33    private CommentsRepository $commentsRepository;
34
35    /**
36     * Constructor.
37     */
38    public function __construct(Configuration $configuration, ?CommentsRepository $commentsRepository = null)
39    {
40        $this->commentsRepository = $commentsRepository ?? new CommentsRepository($configuration);
41    }
42
43    /**
44     * Returns all user comments from a record by type.
45     *
46     * @param int $referenceId record id
47     * @param string $type record type: {faq|news}
48     *
49     * @return Comment[]
50     */
51    public function getCommentsData(int $referenceId, string $type): array
52    {
53        $comments = [];
54
55        $rows = $this->commentsRepository->fetchByReferenceIdAndType($referenceId, $type);
56        foreach ($rows as $row) {
57            $comment = new Comment();
58            $comment
59                ->setId((int) $row->id_comment)
60                ->setRecordId((int) $row->id)
61                ->setComment((string) $row->comment)
62                ->setDate(Date::createIsoDateFromUnixTimestamp((int) $row->datum, DateTimeInterface::ATOM))
63                ->setUsername((string) $row->usr)
64                ->setEmail((string) $row->email)
65                ->setType($type);
66            $comments[] = $comment;
67        }
68
69        return $comments;
70    }
71
72    /**
73     * Returns paginated user comments from a record by type.
74     *
75     * @param int $referenceId Record ID
76     * @param string $type Record type: {faq|news}
77     * @param int $limit Items per page
78     * @param int $offset Offset for pagination
79     * @param string $sortField Field to sort by
80     * @param string $sortOrder Sort order (ASC or DESC)
81     *
82     * @return Comment[]
83     */
84    public function getCommentsDataPaginated(
85        int $referenceId,
86        string $type,
87        int $limit,
88        int $offset,
89        string $sortField = 'id_comment',
90        string $sortOrder = 'ASC',
91    ): array {
92        $comments = [];
93
94        $rows = $this->commentsRepository->fetchPaginated($referenceId, $type, $limit, $offset, $sortField, $sortOrder);
95
96        foreach ($rows as $row) {
97            $comment = new Comment();
98            $comment
99                ->setId((int) $row->id_comment)
100                ->setRecordId((int) $row->id)
101                ->setComment((string) $row->comment)
102                ->setDate(Date::createIsoDateFromUnixTimestamp((int) $row->datum, DateTimeInterface::ATOM))
103                ->setUsername((string) $row->usr)
104                ->setEmail((string) $row->email)
105                ->setType($type);
106            $comments[] = $comment;
107        }
108
109        return $comments;
110    }
111
112    /**
113     * Count total comments for a reference ID and type.
114     *
115     * @param int $referenceId Record ID
116     * @param string $type Record type: {faq|news}
117     * @return int
118     */
119    public function countComments(int $referenceId, string $type): int
120    {
121        return $this->commentsRepository->countByReferenceIdAndType($referenceId, $type);
122    }
123
124    /**
125     * Adds a new comment.
126     */
127    public function create(Comment $comment): bool
128    {
129        return $this->commentsRepository->insert($comment);
130    }
131
132    /**
133     * Deletes a comment.
134     *
135     * @param int    $commentId Comment id
136     */
137    public function delete(string $type, int $commentId): bool
138    {
139        return $this->commentsRepository->deleteByTypeAndId($type, $commentId);
140    }
141
142    /**
143     * Returns the number of comments of each FAQ record as an array.
144     *
145     * @param string $type Type of comment: faq or news
146     * @return array<int, int>
147     */
148    public function getNumberOfComments(string $type = CommentType::FAQ): array
149    {
150        $num = [];
151
152        $rows = $this->commentsRepository->countByTypeGroupedByRecordId($type);
153        foreach ($rows as $row) {
154            $num[(int) $row->id] = (int) $row->anz;
155        }
156
157        return $num;
158    }
159
160    /**
161     * Returns the number of comments of each category as an array.
162     * @return array<int>
163     */
164    public function getNumberOfCommentsByCategory(): array
165    {
166        $numbers = [];
167
168        $rows = $this->commentsRepository->countByCategoryForFaq();
169        foreach ($rows as $row) {
170            $numbers[(int) $row->category_id] = (int) $row->number;
171        }
172
173        return $numbers;
174    }
175
176    /**
177     * Returns all comments with their categories.
178     *
179     * @param string $type Type of comment: faq or news
180     * @return Comment[]
181     */
182    public function getAllComments(string $type = CommentType::FAQ): array
183    {
184        $comments = [];
185
186        $rows = $this->commentsRepository->fetchAllWithCategories($type);
187        foreach ($rows as $row) {
188            $comment = new Comment();
189            $comment
190                ->setId((int) $row->comment_id)
191                ->setRecordId((int) $row->record_id)
192                ->setType($type)
193                ->setComment((string) $row->comment)
194                ->setDate((string) $row->comment_date)
195                ->setUsername((string) $row->username)
196                ->setEmail((string) $row->email);
197
198            if (($row->category_id ?? null) !== null) {
199                $comment->setCategoryId((int) $row->category_id);
200            }
201
202            $comments[] = $comment;
203        }
204
205        return $comments;
206    }
207
208    /**
209     * Checks if comments are disabled for the FAQ record.
210     *
211     * @param int    $recordId ID of FAQ or news entry
212     * @param string $recordLang  Language
213     * @param string $commentType Type of comment: faq or news
214     * @return bool false, if comments are disabled
215     */
216    public function isCommentAllowed(int $recordId, string $recordLang, string $commentType = 'faq'): bool
217    {
218        return $this->commentsRepository->isCommentAllowed($recordId, $recordLang, $commentType);
219    }
220}