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 (#173)
by joseph
22:32
created

Config   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 237
Duplicated Lines 0 %

Test Coverage

Coverage 70.47%

Importance

Changes 0
Metric Value
eloc 102
dl 0
loc 237
ccs 105
cts 149
cp 0.7047
rs 8.8798
c 0
b 0
f 0
wmc 44

11 Methods

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