GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#166)
by Ross
06:42
created

Config   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 230
Duplicated Lines 0 %

Test Coverage

Coverage 60.58%

Importance

Changes 0
Metric Value
eloc 100
dl 0
loc 230
c 0
b 0
f 0
rs 8.96
ccs 63
cts 104
cp 0.6058
wmc 43

10 Methods

Rating   Name   Duplication   Size   Complexity  
A calculateEntitiesPath() 0 9 2
B get() 0 29 8
A __construct() 0 19 5
B validateConfig() 0 31 9
A calculateMigrationsDirectory() 0 8 4
A getUnderscoreNamingStrategy() 0 3 1
A calculateEntitiesCustomDataPath() 0 9 2
A getProjectRootDirectory() 0 14 3
A getFilesystemCachePath() 0 8 4
A calculateProxyDir() 0 16 5

How to fix   Complexity   

Complex Class

Complex classes like Config often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Config, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta;
4
5
use Composer\Autoload\ClassLoader;
6
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\TypeHelper;
8
use EdmondsCommerce\DoctrineStaticMeta\Exception\ConfigException;
9
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
10
11
/**
12
 * Class Config
13
 *
14
 * @package EdmondsCommerce\DoctrineStaticMeta
15
 * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
16
 */
17
class Config implements ConfigInterface
18
{
19
20
    private static $projectRootDirectory;
21
    private $config = [];
22
23
    /**
24
     * Config constructor.
25
     *
26
     * @param array|mixed[] $server
27
     *
28
     * @throws ConfigException
29
     * @throws DoctrineStaticMetaException
30
     */
31 16
    public function __construct(array $server)
32
    {
33 16
        foreach (static::REQUIRED_PARAMS as $key) {
34 16
            if (!\array_key_exists($key, $server)) {
35 4
                throw new ConfigException(
36 4
                    'required config param ' . $key . ' is not set in $server'
37
                );
38
            }
39 12
            $this->config[$key] = $server[$key];
40
        }
41 12
        foreach (self::PARAMS as $key) {
42 12
            if (\array_key_exists($key, $server)) {
43 12
                $this->config[$key] = $server[$key];
44 12
                continue;
45
            }
46 12
            $this->config[$key] = $this->get($key);
47
        }
48
49 12
        $this->validateConfig();
50 12
    }
51
52
    /**
53
     * @param string $key
54
     * @param mixed  $default
55
     *
56
     * @return mixed|string
57
     * @throws DoctrineStaticMetaException
58
     */
59 12
    public function get(string $key, $default = ConfigInterface::NO_DEFAULT_VALUE)
60
    {
61 12
        if (!isset(static::REQUIRED_PARAMS[$key])
62 12
            && !isset(static::OPTIONAL_PARAMS_WITH_DEFAULTS[$key])
63 12
            && !isset(static::OPTIONAL_PARAMS_WITH_CALCULATED_DEFAULTS[$key])
64
        ) {
65
            throw new ConfigException(
66
                'Invalid config param '
67
                . $key
68
                . ', should be one of '
69
                . print_r(static::PARAMS, true)
70
            );
71
        }
72 12
        if (isset($this->config[$key])) {
73 12
            return $this->config[$key];
74
        }
75 12
        if (ConfigInterface::NO_DEFAULT_VALUE !== $default) {
76
            return $default;
77
        }
78 12
        if (isset(static::OPTIONAL_PARAMS_WITH_DEFAULTS[$key])) {
79 12
            return static::OPTIONAL_PARAMS_WITH_DEFAULTS[$key];
80
        }
81 12
        if (isset(static::OPTIONAL_PARAMS_WITH_CALCULATED_DEFAULTS[$key])) {
82 12
            $method = static::OPTIONAL_PARAMS_WITH_CALCULATED_DEFAULTS[$key];
83
84 12
            return $this->$method();
85
        }
86
        throw new ConfigException(
87
            'No config set for param ' . $key . ' and no default provided'
88
        );
89
    }
90
91
    /**
92
     * @throws ConfigException
93
     * @throws DoctrineStaticMetaException
94
     */
95 12
    private function validateConfig(): void
96
    {
97 12
        $errors     = [];
98 12
        $typeHelper = new TypeHelper();
99 12
        foreach (ConfigInterface::PARAM_TYPES as $param => $requiredType) {
100 12
            $value = $this->get($param);
101 12
            if (self::TYPE_BOOL === $requiredType
102 12
                && is_numeric($value)
103 12
                && \in_array((int)$value, [0, 1], true)
104
            ) {
105 2
                $this->config[$param] = ($value === 1);
106 2
                continue;
107
            }
108 12
            if (\is_object($value)) {
109 12
                if (!($value instanceof $requiredType)) {
110
                    $actualType = \get_class($value);
111
                    $errors[]   =
112
                        ' ERROR  ' . $param . ' is not an instance of the required object [' . $requiredType . ']'
113
                        . 'currently configured as an object of the class  [' . $actualType . ']';
114
                }
115 12
                continue;
116
            }
117 12
            $actualType = $typeHelper->getType($value);
118 12
            if ($actualType !== $requiredType) {
119
                $valueString = var_export($value, true);
120
                $errors[]    = ' ERROR  ' . $param . ' is not of the required type [' . $requiredType . ']'
121
                               . ' currently configured as type [' . $actualType . '] with value: ' . $valueString;
122
            }
123
        }
124 12
        if ([] !== $errors) {
125
            throw new ConfigException(implode("\n\n", $errors));
126
        }
127 12
    }
128
129
    /**
130
     * Default Entities path, calculated default
131
     *
132
     * @return string
133
     * @throws DoctrineStaticMetaException
134
     */
135 10
    private function calculateEntitiesPath(): string
136
    {
137
        try {
138 10
            return self::getProjectRootDirectory() . '/src/Entities';
139
        } catch (\Exception $e) {
140
            throw new DoctrineStaticMetaException(
141
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
142
                $e->getCode(),
143
                $e
144
            );
145
        }
146
    }
147
148 12
    private function calculateEntitiesCustomDataPath(): string
149
    {
150
        try {
151 12
            return self::getProjectRootDirectory() . '/tests/Assets/Entity/FakerDataFillers';
152
        } catch (\Exception $e) {
153
            throw new DoctrineStaticMetaException(
154
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
155
                $e->getCode(),
156
                $e
157
            );
158
        }
159
    }
160
161
    /**
162
     * Get the absolute path to the root of the current project
163
     *
164
     * It does this by working from the Composer autoloader which we know will be in a certain place in `vendor`
165
     *
166
     * @return string
167
     * @throws DoctrineStaticMetaException
168
     */
169 12
    public static function getProjectRootDirectory(): string
170
    {
171
        try {
172 12
            if (null === self::$projectRootDirectory) {
173
                $reflection                 = new \ts\Reflection\ReflectionClass(ClassLoader::class);
174
                self::$projectRootDirectory = \dirname($reflection->getFileName(), 3);
175
            }
176
177 12
            return self::$projectRootDirectory;
178
        } catch (\Exception $e) {
179
            throw new DoctrineStaticMetaException(
180
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
181
                $e->getCode(),
182
                $e
183
            );
184
        }
185
    }
186
187
    /**
188
     * Default Entities path, calculated default
189
     *
190
     * @return string
191
     * @throws DoctrineStaticMetaException
192
     */
193 12
    private function calculateProxyDir(): string
194
    {
195
        try {
196 12
            $dir = self::getProjectRootDirectory() . '/cache/Proxies';
197 12
            if (!is_dir($dir) && !(mkdir($dir, 0777, true) && is_dir($dir))) {
198
                throw new \RuntimeException(
199
                    'Proxy directory ' . $dir . ' does not exist and failed trying to create it'
200
                );
201
            }
202
203 12
            return $dir;
204
        } catch (\Exception $e) {
205
            throw new DoctrineStaticMetaException(
206
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
207
                $e->getCode(),
208
                $e
209
            );
210
        }
211
    }
212
213
    /**
214
     * @return UnderscoreNamingStrategy
215
     */
216 12
    private function getUnderscoreNamingStrategy(): UnderscoreNamingStrategy
217
    {
218 12
        return new UnderscoreNamingStrategy();
219
    }
220
221
    /**
222
     * @return string
223
     * @throws DoctrineStaticMetaException
224
     */
225 12
    private function getFilesystemCachePath(): string
226
    {
227 12
        $path = self::getProjectRootDirectory() . '/cache/dsm';
228 12
        if (!is_dir($path) && !(mkdir($path, 0777, true) && is_dir($path))) {
229
            throw new \RuntimeException('Failed creating default cache path at ' . $path);
230
        }
231
232 12
        return $path;
233
    }
234
235
    /**
236
     * @return string
237
     * @throws DoctrineStaticMetaException
238
     */
239 12
    private function calculateMigrationsDirectory(): string
240
    {
241 12
        $path = self::getProjectRootDirectory() . '/migrations';
242 12
        if (!is_dir($path) && !(mkdir($path, 0777, true) && is_dir($path))) {
243
            throw new \RuntimeException('Failed creating default migrations directory at ' . $path);
244
        }
245
246 12
        return $path;
247
    }
248
}
249