Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
41.03% covered (danger)
41.03%
16 / 39
33.33% covered (danger)
33.33%
2 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
SystemSettingsRepository
41.03% covered (danger)
41.03%
16 / 39
33.33% covered (danger)
33.33%
2 / 6
47.66
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
 findAll
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 findByKey
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
3.01
 update
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 getValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLogLevelThreshold
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
1<?php
2
3declare(strict_types=1);
4
5namespace App\Domain\SystemSettings\Repository;
6
7use App\Domain\SystemSettings\Data\SystemSettingData;
8use App\Support\Row;
9use PDO;
10use RuntimeException;
11
12/**
13 * Repository for system settings data access operations.
14 */
15final class SystemSettingsRepository
16{
17    public function __construct(
18        private readonly PDO $pdo,
19    ) {}
20
21    /**
22     * @return SystemSettingData[]
23     */
24    public function findAll(): array
25    {
26        $stmt = $this->pdo->query(
27            'SELECT
28                setting_id as "settingId",
29                setting_key as "settingKey",
30                setting_value as "settingValue",
31                description,
32                updated_by as "updatedBy",
33                created_at as "createdAt",
34                updated_at as "updatedAt"
35            FROM system_settings
36            ORDER BY setting_key',
37        );
38
39        if ($stmt === false) {
40            throw new RuntimeException('Failed to execute query');
41        }
42
43        $settings = [];
44        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
45            $settings[] = new SystemSettingData(Row::from($row));
46        }
47
48        return $settings;
49    }
50
51    public function findByKey(string $key): ?SystemSettingData
52    {
53        $stmt = $this->pdo->prepare(
54            'SELECT
55                setting_id as "settingId",
56                setting_key as "settingKey",
57                setting_value as "settingValue",
58                description,
59                updated_by as "updatedBy",
60                created_at as "createdAt",
61                updated_at as "updatedAt"
62            FROM system_settings
63            WHERE setting_key = :key',
64        );
65
66        if ($stmt === false) {
67            throw new RuntimeException('Failed to prepare statement');
68        }
69        $stmt->execute(['key' => $key]);
70
71        $row = $stmt->fetch(PDO::FETCH_ASSOC);
72
73        return is_array($row) ? new SystemSettingData($row) : null;
74    }
75
76    /**
77     * @param array<mixed> $value
78     * @param string $key
79     * @param ?int $updatedBy
80     */
81    public function update(string $key, array $value, ?int $updatedBy = null): bool
82    {
83        $stmt = $this->pdo->prepare(
84            'UPDATE system_settings
85            SET setting_value = :value,
86                updated_by = :updated_by,
87                updated_at = CURRENT_TIMESTAMP
88             WHERE setting_key = :key',
89        );
90
91        if ($stmt === false) {
92            throw new RuntimeException('Failed to prepare statement');
93        }
94
95        return $stmt->execute([
96            'key' => $key,
97            'value' => json_encode($value),
98            'updated_by' => $updatedBy,
99        ]) && $stmt->rowCount() > 0;
100    }
101
102    /**
103     * @param string $key
104     * @return array<mixed>|null
105     */
106    public function getValue(string $key): ?array
107    {
108        return $this->findByKey($key)?->settingValue;
109    }
110
111    /**
112     * @return array{value: int, level: string}
113     */
114    public function getLogLevelThreshold(): array
115    {
116        $value = $this->getValue('log_level_threshold');
117
118        if ($value === null) {
119            return ['value' => 500, 'level' => 'error'];
120        }
121
122        return [
123            'value' => Row::nullableInt($value, 'value') ?? 500,
124            'level' => Row::nullableString($value, 'level') ?? 'error',
125        ];
126    }
127}