Passed
Push — master ( 8b3fa6...5d65e7 )
by Mr
02:16
created

Config::resolvePath()   B

Complexity

Conditions 10
Paths 16

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 10

Importance

Changes 0
Metric Value
cc 10
eloc 12
c 0
b 0
f 0
nc 16
nop 2
dl 0
loc 24
ccs 13
cts 13
cp 1
crap 10
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace EasyRSA;
6
7
use function count;
8
use EasyRSA\Interfaces\ConfigInterface;
9
use InvalidArgumentException;
10
11
/**
12
 * Class Config.
13
 */
14
class Config implements ConfigInterface
15
{
16
    /**
17
     * Name of file (with or without full path to this file).
18
     */
19
    public string $archive = '.' . DIRECTORY_SEPARATOR . 'easy-rsa.tar.gz';
20
21
    /**
22
     * Path to folder with easy-rsa scripts.
23
     */
24
    public string $scripts = '.' . DIRECTORY_SEPARATOR . 'easy-rsa';
25
26
    /**
27
     * Path to folder with certificates.
28
     */
29
    public string $certs = '.';
30
31
    /**
32
     * List of allowed variables
33
     */
34
    public const ALLOWED = [
35
        'scripts',
36
        'archive',
37
        'certs',
38
    ];
39
40
    /**
41
     * Config constructor.
42
     *
43
     * @param array<string, string> $parameters
44
     */
45 7
    public function __construct(array $parameters = [])
46
    {
47 7
        foreach ($parameters as $key => $value) {
48 1
            $this->set($key, $value);
49
        }
50 7
    }
51
52
    /**
53
     * {@inheritdoc}
54
     *
55
     * @throws \InvalidArgumentException If wrong key name provided
56
     */
57 3
    public function set(string $name, string $value = null, bool $resolveAbsolutePath = true): ConfigInterface
58
    {
59 3
        if (!in_array($name, self::ALLOWED, true)) {
60 2
            throw new InvalidArgumentException('Parameter "' . $name . '" is not in allowed list [' . implode(',', self::ALLOWED) . ']');
61
        }
62
63 1
        $this->$name = $resolveAbsolutePath ? $this->resolvePath($value) : $value;
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type null; however, parameter $path of EasyRSA\Config::resolvePath() does only seem to accept string, 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

63
        $this->$name = $resolveAbsolutePath ? $this->resolvePath(/** @scrutinizer ignore-type */ $value) : $value;
Loading history...
64
65 1
        return $this;
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     *
71
     * @throws \InvalidArgumentException If wrong key name provided
72
     */
73 2
    public function get(string $name): string
74
    {
75 2
        if (!in_array($name, self::ALLOWED, true)) {
76 1
            throw new InvalidArgumentException('Parameter "' . $name . '" is not in allowed list [' . implode(',', self::ALLOWED) . ']');
77
        }
78
79 1
        return $this->$name;
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     *
85
     * @codeCoverageIgnore
86
     */
87
    public function getCerts(): string
88
    {
89
        return $this->get('certs');
90
    }
91
92
    /**
93
     * {@inheritdoc}
94
     *
95
     * @codeCoverageIgnore
96
     */
97
    public function setCerts(string $path): ConfigInterface
98
    {
99
        return $this->set('certs', $path, true);
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     *
105
     * @codeCoverageIgnore
106
     */
107
    public function getScripts(): string
108
    {
109
        return $this->get('scripts');
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     *
115
     * @codeCoverageIgnore
116
     */
117
    public function setScripts(string $path): ConfigInterface
118
    {
119
        return $this->set('scripts', $path, true);
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     *
125
     * @codeCoverageIgnore
126
     */
127
    public function getArchive(): string
128
    {
129
        return $this->get('archive');
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     *
135
     * @codeCoverageIgnore
136
     */
137
    public function setArchive(string $path): ConfigInterface
138
    {
139
        return $this->set('archive', $path, true);
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     */
145 2
    public function resolvePath(string $path, string $basePath = null): string
146
    {
147
        // Make absolute path
148 2
        if (DIRECTORY_SEPARATOR !== $path[0]) {
149 2
            if (null === $basePath) {
150
                // Get PWD first to avoid getcwd() resolving symlinks if in symlinked folder
151 1
                $path = (getenv('PWD') ?: getcwd()) . DIRECTORY_SEPARATOR . $path;
152 1
            } elseif ('' !== $basePath) {
153 1
                $path = $basePath . DIRECTORY_SEPARATOR . $path;
154
            }
155
        }
156
157
        // Resolve '.' and '..'
158 2
        $components = [];
159 2
        foreach (explode(DIRECTORY_SEPARATOR, rtrim($path, DIRECTORY_SEPARATOR)) as $name) {
160 2
            if ('..' === $name) {
161 1
                array_pop($components);
162 2
            } elseif ('.' !== $name && !(count($components) > 0 && '' === $name)) {
163
                // … && !(count($components) && $name === '') - we want to keep initial '/' for abs paths
164 2
                $components[] = $name;
165
            }
166
        }
167
168 2
        return implode(DIRECTORY_SEPARATOR, $components);
169
    }
170
}
171