Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
SystemSettingsService
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 7
380
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAll
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getByKey
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 update
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
20
 getLogLevelThreshold
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 updateLogLevelThreshold
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 validateSetting
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
90
1<?php
2
3declare(strict_types=1);
4
5namespace App\Domain\SystemSettings\Service;
6
7use App\Domain\ErrorLog\Service\ErrorLogService;
8use App\Domain\Exception\NotFoundException;
9use App\Domain\SystemSettings\Data\SystemSettingData;
10use App\Domain\SystemSettings\Repository\SystemSettingsRepository;
11use DomainException;
12use InvalidArgumentException;
13
14/**
15 * Service for system settings business logic.
16 */
17final class SystemSettingsService
18{
19    public function __construct(
20        private readonly SystemSettingsRepository $repository,
21    ) {}
22
23    /**
24     * @return SystemSettingData[]
25     */
26    public function getAll(): array
27    {
28        return $this->repository->findAll();
29    }
30
31    public function getByKey(string $key): ?SystemSettingData
32    {
33        return $this->repository->findByKey($key);
34    }
35
36    /**
37     * @param array<string, mixed> $value
38     * @param string $key
39     * @param int $updatedBy
40     */
41    public function update(string $key, array $value, int $updatedBy): SystemSettingData
42    {
43        if ($this->repository->findByKey($key) === null) {
44            throw new NotFoundException("Setting '{$key}' not found");
45        }
46
47        $this->validateSetting($key, $value);
48
49        if (!$this->repository->update($key, $value, $updatedBy)) {
50            throw new DomainException("Failed to update setting '{$key}'");
51        }
52
53        $updated = $this->repository->findByKey($key);
54
55        if ($updated === null) {
56            throw new DomainException("Failed to retrieve setting '{$key}' after update");
57        }
58
59        return $updated;
60    }
61
62    /**
63     * @return array{value: int, level: string}
64     */
65    public function getLogLevelThreshold(): array
66    {
67        return $this->repository->getLogLevelThreshold();
68    }
69
70    public function updateLogLevelThreshold(string $level, int $updatedBy): SystemSettingData
71    {
72        $levels = ErrorLogService::LOG_LEVELS;
73
74        if (!isset($levels[$level])) {
75            throw new InvalidArgumentException(
76                "Invalid log level '{$level}'. Valid levels: " . implode(', ', array_keys($levels)),
77            );
78        }
79
80        return $this->update('log_level_threshold', [
81            'value' => $levels[$level],
82            'level' => $level,
83        ], $updatedBy);
84    }
85
86    /**
87     * @param array<string, mixed> $value
88     * @param string $key
89     */
90    private function validateSetting(string $key, array $value): void
91    {
92        switch ($key) {
93            case 'log_level_threshold':
94                if (!isset($value['value']) || !isset($value['level'])) {
95                    throw new InvalidArgumentException(
96                        "log_level_threshold must have 'value' and 'level' properties",
97                    );
98                }
99
100                $levels = ErrorLogService::LOG_LEVELS;
101                if (!isset($levels[$value['level']])) {
102                    throw new InvalidArgumentException(
103                        'Invalid log level. Valid levels: ' . implode(', ', array_keys($levels)),
104                    );
105                }
106
107                if ((int)$value['value'] !== $levels[$value['level']]) {
108                    throw new InvalidArgumentException(
109                        "Level value mismatch. '{$value['level']}' should have value {$levels[$value['level']]}",
110                    );
111                }
112                break;
113
114            case 'error_log_retention_days':
115                if (!isset($value['value'])) {
116                    throw new InvalidArgumentException(
117                        "error_log_retention_days must have a 'value' property",
118                    );
119                }
120
121                if ((int)$value['value'] < 0) {
122                    throw new InvalidArgumentException(
123                        'Retention days must be 0 or greater (0 = indefinite)',
124                    );
125                }
126                break;
127        }
128    }
129}