Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
96.67% |
58 / 60 |
|
77.78% |
7 / 9 |
CRAP | |
0.00% |
0 / 1 |
DAO | |
96.67% |
58 / 60 |
|
77.78% |
7 / 9 |
23 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
__destruct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
_ | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
6 | |||
runFile | n/a |
0 / 0 |
n/a |
0 / 0 |
2 | |||||
getDBSchemaVersion | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getMeta | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
setMeta | |
100.00% |
18 / 18 |
|
100.00% |
1 / 1 |
2 | |||
getTestFullState | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
beginTransaction | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
rollBack | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** @noinspection PhpUnhandledExceptionInspection */ |
3 | declare(strict_types=1); |
4 | |
5 | class DAO { |
6 | const tables = [ // because we use different types of DB is difficult to get table list by command |
7 | 'users', |
8 | 'workspaces', |
9 | 'login_sessions', |
10 | 'login_session_groups', |
11 | 'person_sessions', |
12 | 'tests', |
13 | 'units', |
14 | 'admin_sessions', |
15 | 'test_commands', |
16 | 'test_logs', |
17 | 'test_reviews', |
18 | 'logins', |
19 | 'unit_logs', |
20 | 'unit_reviews', |
21 | 'workspace_users', |
22 | 'meta', |
23 | 'unit_data', |
24 | 'files', |
25 | 'unit_defs_attachments', |
26 | 'file_relations' |
27 | ]; |
28 | |
29 | protected ?PDO $pdoDBhandle = null; |
30 | protected int $timeUserIsAllowedInMinutes = 600; |
31 | protected ?string $passwordSalt = 't'; // TODO remove and use SystemConfig |
32 | protected bool $insecurePasswords = false; // TODO remove and use SystemConfig |
33 | protected ?int $lastAffectedRows = null; |
34 | |
35 | public function __construct() { |
36 | $this->pdoDBhandle = DB::getConnection(); |
37 | |
38 | $this->pdoDBhandle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
39 | |
40 | $this->passwordSalt = SystemConfig::$password_salt; |
41 | $this->insecurePasswords = SystemConfig::$debug_useInsecurePasswords; |
42 | } |
43 | |
44 | public function __destruct() { |
45 | if ($this->pdoDBhandle !== null) { |
46 | unset($this->pdoDBhandle); |
47 | $this->pdoDBhandle = null; |
48 | } |
49 | } |
50 | |
51 | public function _(string $sql, array $replacements = [], $multiRow = false): ?array { |
52 | $this->lastAffectedRows = null; |
53 | |
54 | $sqlStatement = $this->pdoDBhandle->prepare($sql); |
55 | |
56 | try { |
57 | $sqlStatement->execute($replacements); |
58 | } catch (Exception $exception) { |
59 | $caller = debug_backtrace(!DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function']; |
60 | throw new Exception($exception->getMessage() . " ($caller)", 0, $exception); |
61 | } |
62 | |
63 | $this->lastAffectedRows = $sqlStatement->rowCount(); |
64 | |
65 | if (!$sqlStatement->columnCount()) { |
66 | return null; |
67 | } |
68 | |
69 | if ($multiRow) { |
70 | $result = $sqlStatement->fetchAll(PDO::FETCH_ASSOC); |
71 | return is_bool($result) ? [] : $result; |
72 | } |
73 | |
74 | $result = $sqlStatement->fetch(PDO::FETCH_ASSOC); |
75 | return is_bool($result) ? null : $result; |
76 | } |
77 | |
78 | /** |
79 | * @codeCoverageIgnore |
80 | */ |
81 | public function runFile(string $path): void { |
82 | if (!file_exists($path)) { |
83 | throw new HttpError("File does not exist: `$path`"); |
84 | } |
85 | |
86 | $this->pdoDBhandle->exec(file_get_contents($path)); |
87 | } |
88 | |
89 | public function getDBSchemaVersion(): string { |
90 | try { |
91 | $result = $this->_("select `value` from meta where metaKey = 'dbSchemaVersion'"); |
92 | return $result['value'] ?? '0.0.0-no-entry'; |
93 | |
94 | } catch (Exception) { |
95 | return '0.0.0-no-table'; |
96 | } |
97 | } |
98 | |
99 | public function getMeta(array $categories): array { |
100 | $categoriesString = implode(',', array_map([$this->pdoDBhandle, "quote"], $categories)); |
101 | $result = $this->_("SELECT * FROM meta where category in ($categoriesString)", [], true); |
102 | $returner = []; |
103 | foreach ($categories as $category) { |
104 | $returner[$category] = []; |
105 | } |
106 | foreach ($result as $row) { |
107 | $returner[$row['category']][$row['metaKey']] = $row['value']; |
108 | } |
109 | return $returner; |
110 | } |
111 | |
112 | public function setMeta(string $category, string $key, ?string $value): void { |
113 | $currentValue = $this->_("select `value` from meta where metaKey = :key", [':key' => $key]); |
114 | |
115 | if (!$currentValue) { |
116 | $this->_( |
117 | "insert into meta (category, metaKey, value) values (:category, :key, :value)", |
118 | [ |
119 | ':key' => $key, |
120 | ':category' => $category, |
121 | ':value' => $value |
122 | ] |
123 | ); |
124 | } else { |
125 | $this->_( |
126 | "update meta set value=:value, category=:category where metaKey = :key", |
127 | [ |
128 | ':key' => $key, |
129 | ':category' => $category, |
130 | ':value' => $value |
131 | ] |
132 | ); |
133 | } |
134 | } |
135 | |
136 | public function getTestFullState(array $testSessionData): array { |
137 | $testState = JSON::decode($testSessionData['testState'] ?? '', true); |
138 | |
139 | if ($testSessionData['locked']) { |
140 | $testState['status'] = 'locked'; |
141 | } else if (!$testSessionData['running']) { |
142 | $testState['status'] = 'pending'; |
143 | } else { |
144 | $testState['status'] = 'running'; |
145 | } |
146 | |
147 | return $testState; |
148 | } |
149 | |
150 | public function beginTransaction(): void { |
151 | $this->pdoDBhandle->beginTransaction(); |
152 | } |
153 | |
154 | public function rollBack(): void { |
155 | $this->pdoDBhandle->rollBack(); |
156 | } |
157 | } |