Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
86 / 86
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
FormsRepository
100.00% covered (success)
100.00%
86 / 86
100.00% covered (success)
100.00%
11 / 11
14
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fetchFormDataByFormId
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 updateInputActive
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 updateInputRequired
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 fetchTranslationsByFormAndInput
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 updateTranslation
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 deleteTranslation
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 fetchDefaultInputData
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 insertTranslationRow
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 insertInput
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 buildInsertQuery
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * Forms repository 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 * @author    Jan Harms <model_railroader@gmx-topmail.de>
13 * @copyright 2025-2026 phpMyFAQ Team
14 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
15 * @link      https://www.phpmyfaq.de
16 * @since     2025-11-04
17 */
18
19declare(strict_types=1);
20
21namespace phpMyFAQ\Form;
22
23use phpMyFAQ\Configuration as CoreConfiguration;
24use phpMyFAQ\Database;
25
26readonly class FormsRepository implements FormsRepositoryInterface
27{
28    public function __construct(
29        private CoreConfiguration $coreConfiguration,
30    ) {
31    }
32
33    /**
34     * @return array<int, \stdClass>
35     */
36    public function fetchFormDataByFormId(int $formId): array
37    {
38        $sql = <<<SQL
39                SELECT
40                    form_id, input_id, input_type, input_label, input_active, input_required, input_lang
41                FROM
42                    %sfaqforms
43                WHERE
44                    form_id = %d
45            SQL;
46
47        $query = sprintf($sql, Database::getTablePrefix(), $formId);
48
49        $result = $this->coreConfiguration->getDb()->query($query);
50        $rows = $this->coreConfiguration->getDb()->fetchAll($result);
51        return is_array($rows) ? $rows : [];
52    }
53
54    public function updateInputActive(int $formId, int $inputId, int $activated): bool
55    {
56        $query = sprintf(
57            'UPDATE %sfaqforms SET input_active = %d WHERE form_id = %d AND input_id = %d',
58            Database::getTablePrefix(),
59            $activated,
60            $formId,
61            $inputId,
62        );
63
64        return (bool) $this->coreConfiguration->getDb()->query($query);
65    }
66
67    public function updateInputRequired(int $formId, int $inputId, int $required): bool
68    {
69        $query = sprintf(
70            'UPDATE %sfaqforms SET input_required = %d WHERE form_id = %d AND input_id = %d',
71            Database::getTablePrefix(),
72            $required,
73            $formId,
74            $inputId,
75        );
76
77        return (bool) $this->coreConfiguration->getDb()->query($query);
78    }
79
80    /**
81     * @return array<int, \stdClass>
82     */
83    public function fetchTranslationsByFormAndInput(int $formId, int $inputId): array
84    {
85        $query = sprintf(
86            'SELECT input_lang, input_label FROM %sfaqforms WHERE form_id = %d AND input_id = %d',
87            Database::getTablePrefix(),
88            $formId,
89            $inputId,
90        );
91
92        $result = $this->coreConfiguration->getDb()->query($query);
93        $rows = $this->coreConfiguration->getDb()->fetchAll($result);
94        return is_array($rows) ? $rows : [];
95    }
96
97    public function updateTranslation(string $label, int $formId, int $inputId, string $lang): bool
98    {
99        $query = sprintf(
100            "UPDATE %sfaqforms SET input_label='%s' WHERE form_id=%d AND input_id=%d AND input_lang='%s'",
101            Database::getTablePrefix(),
102            $this->coreConfiguration->getDb()->escape($label),
103            $formId,
104            $inputId,
105            $this->coreConfiguration->getDb()->escape($lang),
106        );
107
108        return (bool) $this->coreConfiguration->getDb()->query($query);
109    }
110
111    public function deleteTranslation(int $formId, int $inputId, string $lang): bool
112    {
113        $query = sprintf(
114            "DELETE FROM %sfaqforms WHERE form_id=%d AND input_id=%d AND input_lang='%s'",
115            Database::getTablePrefix(),
116            $formId,
117            $inputId,
118            $this->coreConfiguration->getDb()->escape($lang),
119        );
120
121        return (bool) $this->coreConfiguration->getDb()->query($query);
122    }
123
124    public function fetchDefaultInputData(int $formId, int $inputId): ?\stdClass
125    {
126        $query = sprintf(
127            'SELECT input_type, input_active, input_required FROM %sfaqforms WHERE input_id=%d AND form_id=%d '
128            . "AND input_lang='default'",
129            Database::getTablePrefix(),
130            $inputId,
131            $formId,
132        );
133
134        $response = $this->coreConfiguration->getDb()->query($query);
135        $obj = $this->coreConfiguration->getDb()->fetchObject($response);
136
137        return is_object($obj) ? $obj : null;
138    }
139
140    public function insertTranslationRow(
141        int $formId,
142        int $inputId,
143        string $inputType,
144        string $label,
145        int $inputActive,
146        int $inputRequired,
147        string $langCode,
148    ): bool {
149        $query = sprintf(
150            'INSERT INTO %sfaqforms(form_id, input_id, input_type, input_label, input_active, input_required, '
151            . " input_lang) VALUES (%d, %d, '%s', '%s', %d, %d, '%s')",
152            Database::getTablePrefix(),
153            $formId,
154            $inputId,
155            $this->coreConfiguration->getDb()->escape($inputType),
156            $this->coreConfiguration->getDb()->escape($label),
157            $inputActive,
158            $inputRequired,
159            $this->coreConfiguration->getDb()->escape($langCode),
160        );
161
162        return (bool) $this->coreConfiguration->getDb()->query($query);
163    }
164
165    /**
166     * @param array<string, mixed> $input
167     */
168    public function insertInput(array $input): bool
169    {
170        $query = $this->buildInsertQuery($input);
171        return (bool) $this->coreConfiguration->getDb()->query($query);
172    }
173
174    /**
175     * @param array<string, mixed> $input
176     */
177    public function buildInsertQuery(array $input): string
178    {
179        return sprintf(
180            'INSERT INTO %sfaqforms(form_id, input_id, input_type, input_label, input_lang, input_active, '
181            . " input_required) VALUES (%d, %d, '%s', '%s', '%s', %d, %d)",
182            Database::getTablePrefix(),
183            (int) $input['form_id'],
184            (int) $input['input_id'],
185            $this->coreConfiguration->getDb()->escape((string) $input['input_type']),
186            $this->coreConfiguration->getDb()->escape((string) $input['input_label']),
187            $this->coreConfiguration->getDb()->escape((string) $input['input_lang']),
188            (int) $input['input_active'],
189            (int) $input['input_required'],
190        );
191    }
192}