Passed
Push — main ( 0ba104...db6621 )
by Thierry
03:02
created

UserFileReader::userMatches()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 2
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Lagdo\DbAdmin\Config;
4
5
use Jaxon\Config\ConfigReader;
6
use Jaxon\Config\ConfigSetter;
7
8
use function array_map;
9
use function array_filter;
10
use function array_values;
11
use function count;
12
use function env;
0 ignored issues
show
introduced by
The function env was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
13
use function in_array;
14
use function is_array;
15
use function is_file;
16
use function is_string;
17
18
class UserFileReader
19
{
20
    /**
21
     * The constructor
22
     *
23
     * @param AuthInterface $auth
24
     * @param string $configFilePath
25
     * @param bool $useEnv
26
     */
27
    public function __construct(private AuthInterface $auth,
28
        private string $configFilePath, private bool $useEnv = false)
29
    {}
30
31
    /**
32
     * @param array $server
33
     *
34
     * @return bool
35
     */
36
    private function checkServer(array $server): bool
37
    {
38
        if (!isset($server['name']) || !isset($server['driver'])) {
39
            return false;
40
        }
41
        if ($server['driver'] === 'sqlite') {
42
            return isset($server['directory']) && count($server) === 3;
43
        }
44
        return isset($server['host']) && isset($server['port']) &&
45
            isset($server['username']) && isset($server['password']) &&
46
            count($server) === 6;
47
    }
48
49
    /**
50
     * @param array $options
51
     *
52
     * @return bool
53
     */
54
    private function checkUser(array $options): bool
55
    {
56
        $user = $options['id']['user'] ?? null;
57
        return is_string($user) && $this->auth->user() === $user;
58
    }
59
60
    /**
61
     * @param array $options
62
     *
63
     * @return bool
64
     */
65
    private function checkUsers(array $options): bool
66
    {
67
        $users = $options['id']['users'] ?? null;
68
        return is_array($users) && in_array($this->auth->user(), $users);
69
    }
70
71
    /**
72
     * @param array $options
73
     *
74
     * @return bool
75
     */
76
    private function checkRole(array $options): bool
77
    {
78
        $role = $options['id']['role'] ?? null;
79
        return is_string($role) && $this->auth->role() === $role;
80
    }
81
82
    /**
83
     * @param array $options
84
     *
85
     * @return bool
86
     */
87
    private function checkRoles(array $options): bool
88
    {
89
        $roles = $options['id']['roles'] ?? null;
90
        return is_array($roles) && in_array($this->auth->role(), $roles);
91
    }
92
93
    /**
94
     * @param array $options
95
     *
96
     * @return bool
97
     */
98
    private function userMatches(array $options): bool
99
    {
100
        return $this->checkUser($options) || $this->checkUsers($options) ||
101
            $this->checkRole($options) || $this->checkRoles($options);
102
    }
103
104
    /**
105
     * Replace options with values from the .env config.
106
     *
107
     * @param array $values
108
     *
109
     * @return array
110
     */
111
    private function getOptionValues(array $values): array
112
    {
113
        // Filter the servers list on valid entries
114
        $values['servers'] = array_filter($values['servers'] ?? [],
115
            fn(array $server) => $this->checkServer($server));
116
        if (!$this->useEnv) {
117
            return $values;
118
        }
119
120
        // The values in the server options are the names of the
121
        // corresponding options in the .env file.
122
        $options = ['host', 'port', 'username', 'password'];
123
        $values['servers'] = array_map(function(array $server) use($options) {
124
            if ($server['driver'] !== 'sqlite') {
125
                foreach ($options as $option) {
126
                    $server[$option] = env($server[$option]);
0 ignored issues
show
Bug introduced by
The function env was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

126
                    $server[$option] = /** @scrutinizer ignore-call */ env($server[$option]);
Loading history...
127
                }
128
            }
129
            return $server;
130
        }, $values['servers'] ?? []);
131
        return $values;
132
    }
133
134
    /**
135
     * Get the options for the authenticated user.
136
     *
137
     * @param array $defaultOptions
138
     *
139
     * @return array
140
     */
141
    public function getOptions(array $defaultOptions): array
142
    {
143
        // If the config file doesn't exists, return an empty array.
144
        if (!is_file($this->configFilePath)) {
145
            return [];
146
        }
147
148
        // The key to use for the user options
149
        $userKey = 'user';
150
        // Remove the provider field.
151
        unset($defaultOptions['provider']);
152
153
        $setter = new ConfigSetter();
154
        $reader = new ConfigReader($setter);
155
        $userConfig = $setter->newConfig([$userKey => $defaultOptions]);
156
157
        $config = $reader->load($setter->newConfig(), $this->configFilePath);
158
        $commonOptions = $config->getOption('common', null);
159
        if (is_array($commonOptions)) {
160
            $userConfig = $setter->setOptions($userConfig, $commonOptions, $userKey);
161
        }
162
163
        $fallbackOptions = $config->getOption('fallback', null);
164
165
        $userList = $config->getOption('users', []);
166
        $userList = array_values(array_filter($userList,
167
            fn($options) => $this->userMatches($options)));
168
        $userOptions = $userList[0] ?? $fallbackOptions;
169
170
        if (!is_array($userOptions)) {
171
            return $this->getOptionValues($userConfig->getOption($userKey));
0 ignored issues
show
Bug introduced by
It seems like $userConfig->getOption($userKey) can also be of type null; however, parameter $values of Lagdo\DbAdmin\Config\Use...ader::getOptionValues() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

171
            return $this->getOptionValues(/** @scrutinizer ignore-type */ $userConfig->getOption($userKey));
Loading history...
172
        }
173
174
        unset($userOptions['id']); // Remove the id field.
175
        $userConfig = $setter->setOptions($userConfig, $userOptions, $userKey);
176
177
        return $this->getOptionValues($userConfig->getOption($userKey));
178
    }
179
}
180