Passed
Push — master ( e1084c...1b59a4 )
by Fabien
02:20
created

Loader::validate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 11
rs 10
cc 2
nc 2
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Churn\Configuration;
6
7
use Churn\Configuration\Validator\CachePath;
8
use Churn\Configuration\Validator\CommitsSince;
9
use Churn\Configuration\Validator\DirectoriesToScan;
10
use Churn\Configuration\Validator\FileExtensions;
11
use Churn\Configuration\Validator\FilesToIgnore;
12
use Churn\Configuration\Validator\FilesToShow;
13
use Churn\Configuration\Validator\Hooks;
14
use Churn\Configuration\Validator\MaxScoreThreshold;
15
use Churn\Configuration\Validator\MinScoreToShow;
16
use Churn\Configuration\Validator\ParallelJobs;
17
use Churn\Configuration\Validator\Vcs;
18
use InvalidArgumentException;
19
use Symfony\Component\Yaml\Exception\ParseException;
20
use Symfony\Component\Yaml\Yaml;
21
22
/**
23
 * @internal
24
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
25
 */
26
class Loader
27
{
28
    /**
29
     * @param string $confPath Path of the configuration file to load.
30
     * @param boolean $isDefaultValue Indicates whether $confPath contains the default value.
31
     * @throws InvalidArgumentException If the configuration file cannot be loaded.
32
     */
33
    public static function fromPath(string $confPath, bool $isDefaultValue): Config
34
    {
35
        $confPath = self::normalizePath($originalConfPath = $confPath);
36
37
        if (false !== $confPath && \is_readable($confPath)) {
38
            $config = new EditableConfig($confPath);
39
            $config->setUnrecognizedKeys(self::validate($config, self::loadYaml($confPath)));
40
41
            return $config;
42
        }
43
44
        if ($isDefaultValue) {
45
            return new Config();
46
        }
47
48
        throw new InvalidArgumentException('The configuration file can not be read at ' . $originalConfPath);
49
    }
50
51
    /**
52
     * @param string $confPath Path to normalize.
53
     * @return string|false
54
     */
55
    private static function normalizePath(string $confPath)
56
    {
57
        if (\is_dir($confPath)) {
58
            $confPath = \rtrim($confPath, '/\\') . '/churn.yml';
59
        }
60
61
        return \realpath($confPath);
62
    }
63
64
    /**
65
     * @param string $confPath Path of the yaml file to load.
66
     * @return array<mixed>
67
     * @throws InvalidArgumentException If the configuration file is invalid.
68
     */
69
    private static function loadYaml(string $confPath): array
70
    {
71
        try {
72
            $content = Yaml::parse((string) \file_get_contents($confPath)) ?? [];
73
        } catch (ParseException $e) {
74
            $content = null;
75
        }
76
77
        if (!\is_array($content)) {
78
            throw new InvalidArgumentException('The content of the configuration file is invalid');
79
        }
80
81
        return $content;
82
    }
83
84
    /**
85
     * @param EditableConfig $config The configuration object.
86
     * @param array<mixed> $configuration The array containing the configuration values.
87
     * @return array<int|string>
88
     */
89
    private static function validate(EditableConfig $config, array $configuration): array
90
    {
91
        $validators = [new CachePath(), new CommitsSince(), new DirectoriesToScan(), new FileExtensions(),
92
        new FilesToIgnore(), new FilesToShow(), new Hooks(), new MaxScoreThreshold(), new MinScoreToShow(),
93
        new ParallelJobs(), new Vcs()];
94
        foreach ($validators as $validator) {
95
            $validator->validate($config, $configuration);
96
            unset($configuration[$validator->getKey()]);
97
        }
98
99
        return \array_keys($configuration);
100
    }
101
}
102