Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
SqlSettingsRepository
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
5 / 5
15
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
 get
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 fetchRawSetting
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 fetchFromPdo
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 getInt
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Settings;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Core\Api\ApiClientInterface;
12use App\Core\Settings\Presentation\Api\SettingsApiController;
13use PDO;
14use Throwable;
15
16/**
17 * SQL & API Implementation of SettingsRepositoryInterface.
18 *
19 * Reads system parameters through REST API /api/v1/settings with direct fallback.
20 *
21 * @package App\Core\Settings
22 */
23final class SqlSettingsRepository implements SettingsRepositoryInterface
24{
25    /** @var array<string, string> In-memory cached settings map. */
26    private array $cache = [];
27
28    /**
29     * SqlSettingsRepository constructor.
30     *
31     * @param SettingsApiController|ApiClientInterface|PDO $source API Controller, ApiClient or PDO connection.
32     * @param string $tablePrefix Database table prefix.
33     */
34    public function __construct(
35        private readonly SettingsApiController|ApiClientInterface|PDO $source,
36        private readonly string $tablePrefix = 'a_'
37    ) {
38    }
39
40    /**
41     * Retrieves setting string value by key name.
42     *
43     * @param string $key Setting unique key name.
44     * @param string $default Default fallback string value.
45     * @return string Setting value.
46     */
47    public function get(string $key, string $default = ''): string
48    {
49        if (isset($this->cache[$key])) {
50            return $this->cache[$key];
51        }
52
53        try {
54            $val = $this->fetchRawSetting($key);
55            if ($val !== null) {
56                $this->cache[$key] = $val;
57            }
58            return $this->cache[$key] ?? $default;
59        } catch (Throwable) {
60            return $default;
61        }
62    }
63
64    /**
65     * Fetches raw setting value from configured source.
66     *
67     * @param string $key Setting key.
68     * @return string|null Setting string value if found.
69     */
70    private function fetchRawSetting(string $key): ?string
71    {
72        if ($this->source instanceof SettingsApiController) {
73            return $this->source->getSettingFromDb($key);
74        }
75
76        if ($this->source instanceof ApiClientInterface) {
77            $res = $this->source->get('/api/v1/settings/' . $key);
78            return (!empty($res['status']) && isset($res['value'])) ? (string)$res['value'] : null;
79        }
80
81        return $this->fetchFromPdo($key);
82    }
83
84    /**
85     * Fetches setting string from direct PDO connection.
86     *
87     * @param string $key Setting key.
88     * @return string|null Setting string value.
89     */
90    private function fetchFromPdo(string $key): ?string
91    {
92        $tableName = $this->tablePrefix . 'core_settings_records';
93        $sql = sprintf('SELECT `setting_value` FROM `%s` WHERE `setting_key` = :key LIMIT 1', $tableName);
94        /** @var PDO $pdo */
95        $pdo = $this->source;
96        $stmt = $pdo->prepare($sql);
97        $stmt->execute([':key' => $key]);
98        $val = $stmt->fetchColumn();
99        return ($val !== false && $val !== null) ? (string)$val : null;
100    }
101
102    /**
103     * Retrieves integer setting value.
104     *
105     * @param string $key Setting key name.
106     * @param int $default Default integer fallback.
107     * @return int Parsed integer value.
108     */
109    public function getInt(string $key, int $default = 0): int
110    {
111        $val = $this->get($key, (string)$default);
112
113        return is_numeric($val) ? (int)$val : $default;
114    }
115}