Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3/**
4 * FAQ repository interface for phpMyFAQ.
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 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     2026-06-29
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Faq;
21
22use phpMyFAQ\Entity\FaqEntity;
23
24interface FaqRepositoryInterface
25{
26    /**
27     * Returns the next available solution id.
28     */
29    public function getNextSolutionId(): int;
30
31    /**
32     * Returns the solution id for a given FAQ id and language, or the next available
33     * solution id when the FAQ does not exist yet.
34     */
35    public function getSolutionIdFromId(int $faqId, string $faqLang): int;
36
37    /**
38     * Checks whether a FAQ already exists in the given language.
39     */
40    public function hasTranslation(int $faqId, string $faqLang): bool;
41
42    /**
43     * Checks whether a FAQ record is visible to the given user and groups in the
44     * given language: active, within its active date window, and permitted.
45     *
46     * @param int[] $groups
47     */
48    public function isFaqVisibleForUser(
49        int $faqId,
50        string $faqLang,
51        int $userId,
52        array $groups,
53        bool $groupSupport,
54    ): bool;
55
56    /**
57     * Checks whether a FAQ (or news) record is active.
58     */
59    public function isActive(int $faqId, string $faqLang, string $commentType = 'faq'): bool;
60
61    /**
62     * Resolves a solution id to the FAQ id, language, question, content and category id,
63     * honouring the given user and group permissions. Returns an empty array when nothing
64     * matches.
65     *
66     * @param int[] $groups
67     * @return array<string, mixed>
68     */
69    public function getIdFromSolutionId(int $solutionId, int $userId, array $groups, bool $groupSupport): array;
70
71    /**
72     * Fetches the raw question (thema) of a FAQ in the given language, or null when the
73     * FAQ does not exist.
74     */
75    public function fetchQuestion(int $faqId, string $language): ?string;
76
77    /**
78     * Fetches the raw, unescaped keywords of a FAQ in the given language, or null when the
79     * FAQ does not exist.
80     */
81    public function fetchKeywords(int $faqId, string $language): ?string;
82
83    /**
84     * Runs the permission-filtered query for a single FAQ (or FAQ revision) and returns the
85     * raw database result handle. Admin callers bypass the permission filter.
86     *
87     * @param int[] $groups
88     */
89    public function getFaqResult(
90        int $faqId,
91        string $faqLanguage,
92        ?int $faqRevisionId,
93        bool $isAdmin,
94        int $userId,
95        array $groups,
96        bool $groupSupport,
97    ): mixed;
98
99    /**
100     * Fetches a single FAQ scoped to a category, honouring user and group permissions, in the
101     * configuration's current language. Returns the raw row, or null when nothing matches.
102     *
103     * @param int[] $groups
104     */
105    public function fetchFaqByIdAndCategoryId(
106        int $faqId,
107        int $categoryId,
108        bool $onlyActive,
109        int $userId,
110        array $groups,
111        bool $groupSupport,
112    ): ?object;
113
114    /**
115     * Resolves a solution id to its FAQ row, honouring user and group permissions and falling
116     * back to an unrestricted record when the FAQ has no access restrictions. Returns the raw
117     * row, or null when nothing matches.
118     *
119     * @param int[] $groups
120     */
121    public function fetchRowBySolutionId(int $solutionId, int $userId, array $groups, bool $groupSupport): ?object;
122
123    /**
124     * Fetches the active, non-expired FAQs of a category in the current language, ordered by
125     * the given (already validated) table/column/direction and filtered by permissions.
126     * Returns the raw rows.
127     *
128     * @param int[] $groups
129     * @return \stdClass[]
130     */
131    public function fetchAvailableFaqsByCategoryId(
132        int $categoryId,
133        string $orderTable,
134        string $orderColumn,
135        string $sortDirection,
136        int $userId,
137        array $groups,
138        bool $groupSupport,
139    ): array;
140
141    /**
142     * Fetches the FAQs whose ids are in the given comma-separated list, in the current language
143     * and filtered by permissions. Returns the raw rows.
144     *
145     * @param int[] $groups
146     * @return \stdClass[]
147     */
148    public function fetchFaqsByIds(
149        string $records,
150        bool $onlyActive,
151        int $userId,
152        array $groups,
153        bool $groupSupport,
154    ): array;
155
156    /**
157     * Fetches the active sticky FAQs of the current language ordered by visits, filtered by
158     * permissions. Returns the raw rows.
159     *
160     * @param int[] $groups
161     * @return \stdClass[]
162     */
163    public function fetchStickyFaqs(int $userId, array $groups, bool $groupSupport): array;
164
165    /**
166     * Fetches all FAQs matching an optional field => condition map, with the given (already
167     * validated) ORDER BY clause and filtered by permissions. Returns the raw rows.
168     *
169     * @param array<string, mixed>|null $condition
170     * @param int[]                     $groups
171     * @return \stdClass[]
172     */
173    public function fetchAllFaqs(
174        ?array $condition,
175        string $orderBy,
176        int $userId,
177        array $groups,
178        bool $groupSupport,
179    ): array;
180
181    /**
182     * Inserts a new FAQ row. The entity must already carry its id, solution id and revision id.
183     */
184    public function insert(FaqEntity $faqEntity): void;
185
186    /**
187     * Updates an existing FAQ row identified by the entity's id and language.
188     */
189    public function update(FaqEntity $faqEntity): void;
190
191    /**
192     * Deletes a FAQ and its related rows (category relations, revisions, visits, permissions,
193     * tags, comments, votes, bookmarks, changelog) across all affected tables.
194     */
195    public function deleteByIdAndLanguage(int $faqId, string $faqLang): void;
196
197    /**
198     * Runs the category FAQ-list query used for HTML rendering and returns the raw database
199     * result handle. Pass offset/rowcount to fetch a single page; a rowcount of 0 fetches all.
200     *
201     * @param int[] $groups
202     */
203    public function queryRenderableFaqsByCategoryId(
204        int $categoryId,
205        string $order,
206        int $userId,
207        array $groups,
208        bool $groupSupport,
209        int $offset = 0,
210        int $rowcount = 0,
211    ): mixed;
212
213    /**
214     * Counts the renderable FAQs of one category for the given permission context,
215     * matching the filters of queryRenderableFaqsByCategoryId().
216     *
217     * @param int[] $groups
218     */
219    public function countRenderableFaqsByCategoryId(
220        int $categoryId,
221        int $userId,
222        array $groups,
223        bool $groupSupport,
224    ): int;
225
226    /**
227     * Runs the id-list FAQ query used for HTML rendering and returns the raw database result
228     * handle (the caller paginates it).
229     *
230     * @param int[] $groups
231     */
232    public function queryRenderableFaqsByIds(
233        string $records,
234        string $orderExpression,
235        string $sortDirection,
236        int $userId,
237        array $groups,
238        bool $groupSupport,
239    ): mixed;
240}