Completed
Push — master ( 3613af...29cdc6 )
by Mr
01:35
created

Config::throwIfNotInArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 4
cp 0.75
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2.0625
1
<?php
2
3
namespace OpenVPN;
4
5
use OpenVPN\Interfaces\ConfigInterface;
6
7
class Config implements ConfigInterface
8
{
9
    /**
10
     * Array with all certificates
11
     * @var array
12
     */
13
    private $_certs = [];
14
15
    /**
16
     * List of lines which must be pushed to clients
17
     * @var array
18
     */
19
    private $_pushes = [];
20
21
    /**
22
     * All parameters added via addParam method
23
     * @var array
24
     */
25
    private $_params = [];
26
27
    /**
28
     * Generate config by parameters in memory
29
     *
30
     * @return  string
31
     */
32
    public function generate(): string
33
    {
34
        // Init the variable
35
        $config = '';
36
37
        foreach ($this->getParams() as $key => $value) {
38
            $config .= $key . ((\strlen($value) > 0) ? ' ' . $value : '') . "\n";
39
        }
40
41
        $certs = $this->getCerts();
42
        if (\count($certs) > 0) {
43
            $config .= "\n### Certificates\n";
44
            foreach ($this->getCerts() as $key => $value) {
45
                $config .= isset($value['content'])
46
                    ? "<$key>\n{$value['content']}\n</$key>\n"
47
                    : "$key {$value['path']}\n";
48
            }
49
        }
50
51
        $pushes = $this->getPushes();
52
        if (\count($pushes) > 0) {
53
            $config .= "\n### Networking\n";
54
            foreach ($this->getPushes() as $push) {
55
                $config .= 'push "' . $push . "\"\n";
56
            }
57
        }
58
59
        return $config;
60
    }
61
62
    /**
63
     * Import content of all listed certificates
64
     */
65
    public function importCerts()
66
    {
67
        foreach ($this->_certs as $cert) {
68
            $cert['content'] = rtrim(file_get_contents($cert['path']));
69
        }
70
    }
71
72 3
    private function throwIfNotInArray($key, $array)
73
    {
74 3
        if (!\in_array($key, $array, true)) {
75
            throw new \RuntimeException("Key '$key' not in list of allowed [" . implode(',', $array) . ']');
76
        }
77 3
    }
78
79
    /**
80
     * Add new cert into the configuration
81
     *
82
     * @param   string $type Type of certificate [ca, cert, key, dh, tls-auth]
83
     * @param   string $pathOrContent Absolute or relative path to certificate or content of this file
84
     * @param   bool if content of file is provided
85
     * @throws  \RuntimeException
86
     * @return  ConfigInterface
87
     */
88 3
    public function addCert(string $type, string $pathOrContent, bool $isContent = false): ConfigInterface
89
    {
90 3
        $type = mb_strtolower($type);
91 3
        $this->throwIfNotInArray($type, self::CERTS);
92 3
        if (true === $isContent) {
93 1
            $this->_certs[$type]['content'] = $pathOrContent;
94
        } else {
95 3
            $this->_certs[$type]['path'] = $pathOrContent;
96
        }
97 3
        return $this;
98
    }
99
100
    /**
101
     * Remove selected certificate from array
102
     *
103
     * @param   string $type Type of certificate [ca, cert, key, dh, tls-auth]
104
     * @throws  \RuntimeException
105
     * @return  ConfigInterface
106
     */
107 2
    public function delCert(string $type): ConfigInterface
108
    {
109 2
        $type = mb_strtolower($type);
110 2
        $this->throwIfNotInArray($type, self::CERTS);
111 2
        unset($this->_certs[$type]);
112 2
        return $this;
113
    }
114
115
    /**
116
     * Return information about specified certificate
117
     *
118
     * @param   string $type
119
     * @throws  \RuntimeException
120
     * @return  array
121
     */
122
    public function getCert(string $type): array
123
    {
124
        $type = mb_strtolower($type);
125
        $this->throwIfNotInArray($type, self::CERTS);
126
        return $this->_certs[$type] ?? [];
127
    }
128
129
    /**
130
     * Get full list of certificates
131
     *
132
     * @return  array
133
     */
134 3
    public function getCerts(): array
135
    {
136 3
        return $this->_certs;
137
    }
138
139
    /**
140
     * Append new push into the array
141
     *
142
     * @param   string $line String with line which must be pushed
143
     * @return  ConfigInterface
144
     */
145
    public function addPush(string $line): ConfigInterface
146
    {
147
        $this->_pushes[] = trim($line, '"');
148
        return $this;
149
    }
150
151
    /**
152
     * Remove route line from push array
153
     *
154
     * @param   string $line String with line which must be pushed
155
     * @return  ConfigInterface
156
     */
157
    public function delPush(string $line): ConfigInterface
158
    {
159
        unset($this->_pushes[$line]);
160
        return $this;
161
    }
162
163
    /**
164
     * Get all pushes from array
165
     *
166
     * @return  array
167
     */
168
    public function getPushes(): array
169
    {
170
        return $this->_pushes;
171
    }
172
173
    /**
174
     * Check if value is boolean, if not then return same string
175
     *
176
     * @param   mixed $value
177
     * @return  mixed
178
     */
179
    private function isBool($value)
180
    {
181
        if (\is_bool($value)) {
182
            $value = $value ? 'true' : 'false';
183
        }
184
        return $value;
185
    }
186
187
    /**
188
     * Add some new parameter to the list of parameters
189
     *
190
     * @example $this->add('client')->add('remote', 'vpn.example.com');
191
     * @param   string $name Name of parameter
192
     * @param   string|bool|null $value Value of parameter
193
     * @return  ConfigInterface
194
     */
195
    public function add(string $name, $value = null): ConfigInterface
196
    {
197
        $name = mb_strtolower($name);
198
199
        // Check if key is certificate or push, or classic parameter
200
        if (\in_array($name, self::CERTS, true)) {
201
            $this->addCert($name, $value);
0 ignored issues
show
Bug introduced by
It seems like $value defined by parameter $value on line 195 can also be of type boolean or null; however, OpenVPN\Config::addCert() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
202
        } elseif ($name === 'push') {
203
            $this->addPush($value);
0 ignored issues
show
Bug introduced by
It seems like $value defined by parameter $value on line 195 can also be of type boolean or null; however, OpenVPN\Config::addPush() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
204
        } else {
205
            $this->_params[$name] = $this->isBool($value);
206
        }
207
208
        return $this;
209
    }
210
211
    /**
212
     * Get some custom element
213
     *
214
     * @param   string|null $name Name of parameter
215
     * @return  mixed
216
     */
217
    public function get(string $name)
218
    {
219
        return $this->_params[$name] ?? null;
220
    }
221
222
    /**
223
     * Get full list of parameters, or some custom element
224
     *
225
     * @return  array
226
     */
227
    public function getParams(): array
228
    {
229
        return $this->_params;
230
    }
231
232
    /**
233
     * Remove some parameter from array by name
234
     *
235
     * @param   string $name Name of parameter
236
     * @throws  \RuntimeException
237
     * @return  ConfigInterface
238
     */
239
    public function del(string $name): ConfigInterface
240
    {
241
        // Check if key is certificate or push, or classic parameter
242
        if (\in_array($name, self::CERTS, true)) {
243
            $this->delCert($name);
244
        } elseif ($name === 'push') {
245
            throw new \RuntimeException("Not possible to remove push, use 'delPush' instead");
246
        } else {
247
            $this->_params = array_map(
248
                function($param) use ($name) {
249
                    return ($param['name'] === $name) ? null : $param;
250
                },
251
                $this->_params
252
            );
253
        }
254
255
        return $this;
256
    }
257
}
258