• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / version-bumper / 12817701920

16 Jan 2025 09:13PM UTC coverage: 89.688% (+0.04%) from 89.652%
12817701920

push

github

web-flow
Merge pull request #28 from eliashaeussler/feature/php-config

18 of 19 new or added lines in 1 file covered. (94.74%)

861 of 960 relevant lines covered (89.69%)

4.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.36
/src/Config/ConfigReader.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the Composer package "eliashaeussler/version-bumper".
7
 *
8
 * Copyright (C) 2024-2025 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\VersionBumper\Config;
25

26
use CuyZ\Valinor;
27
use EliasHaeussler\VersionBumper\Exception;
28
use SplFileObject;
29
use Symfony\Component\Filesystem;
30
use Symfony\Component\Yaml;
31

32
use function dirname;
33
use function is_callable;
34

35
/**
36
 * ConfigReader.
37
 *
38
 * @author Elias Häußler <elias@haeussler.dev>
39
 * @license GPL-3.0-or-later
40
 */
41
final class ConfigReader
42
{
43
    private readonly Filesystem\Filesystem $filesystem;
44
    private readonly Valinor\Mapper\TreeMapper $mapper;
45

46
    public function __construct()
17✔
47
    {
48
        $this->filesystem = new Filesystem\Filesystem();
17✔
49
        $this->mapper = $this->createMapper();
17✔
50
    }
51

52
    /**
53
     * @throws Exception\ConfigFileIsInvalid
54
     * @throws Exception\ConfigFileIsNotSupported
55
     * @throws Exception\FileDoesNotExist
56
     * @throws Valinor\Mapper\MappingError
57
     */
58
    public function readFromFile(string $file): VersionBumperConfig
15✔
59
    {
60
        if (!$this->filesystem->exists($file)) {
15✔
61
            throw new Exception\FileDoesNotExist($file);
1✔
62
        }
63

64
        $extension = Filesystem\Path::getExtension($file, true);
14✔
65

66
        if ('php' === $extension) {
14✔
67
            $config = $this->parsePhpFile($file);
3✔
68
        } else {
69
            $source = match ($extension) {
11✔
70
                'json' => Valinor\Mapper\Source\Source::file(new SplFileObject($file)),
8✔
71
                'yaml', 'yml' => Valinor\Mapper\Source\Source::array($this->parseYamlFile($file)),
2✔
72
                default => throw new Exception\ConfigFileIsNotSupported($file),
1✔
73
            };
11✔
74
            $config = $this->mapper->map(VersionBumperConfig::class, $source);
9✔
75
        }
76

77
        if (null === $config->rootPath()) {
10✔
78
            $config->setRootPath(dirname($file));
1✔
79
        } elseif (!Filesystem\Path::isAbsolute($config->rootPath())) {
9✔
80
            $config->setRootPath(
9✔
81
                Filesystem\Path::makeAbsolute($config->rootPath(), dirname($file)),
9✔
82
            );
9✔
83
        }
84

85
        foreach ($config->presets() as $preset) {
10✔
86
            $config = $config->merge($preset->getConfig());
5✔
87
        }
88

89
        return $config;
10✔
90
    }
91

92
    public function detectFile(string $rootPath): ?string
2✔
93
    {
94
        $filenames = [
2✔
95
            'version-bumper.php',
2✔
96
            'version-bumper.json',
2✔
97
            'version-bumper.yaml',
2✔
98
            'version-bumper.yml',
2✔
99
        ];
2✔
100

101
        foreach ($filenames as $filename) {
2✔
102
            $path = Filesystem\Path::join($rootPath, $filename);
2✔
103

104
            if ($this->filesystem->exists($path)) {
2✔
105
                return $path;
1✔
106
            }
107
        }
108

109
        return null;
1✔
110
    }
111

112
    /**
113
     * @throws Exception\ConfigFileIsInvalid
114
     */
115
    private function parsePhpFile(string $file): VersionBumperConfig
3✔
116
    {
117
        $returnValue = require $file;
3✔
118

119
        if ($returnValue instanceof VersionBumperConfig) {
3✔
120
            return $returnValue;
1✔
121
        }
122

123
        if (!is_callable($returnValue)) {
2✔
124
            throw new Exception\ConfigFileIsInvalid($file);
1✔
125
        }
126

127
        $config = $returnValue();
1✔
128

129
        if (!($config instanceof VersionBumperConfig)) {
1✔
NEW
130
            throw new Exception\ConfigFileIsInvalid($file);
×
131
        }
132

133
        return $config;
1✔
134
    }
135

136
    /**
137
     * @return array<array-key, mixed>
138
     *
139
     * @throws Exception\ConfigFileIsInvalid
140
     */
141
    private function parseYamlFile(string $file): array
2✔
142
    {
143
        $yaml = Yaml\Yaml::parseFile($file);
2✔
144

145
        if (!is_array($yaml)) {
2✔
146
            throw new Exception\ConfigFileIsInvalid($file);
1✔
147
        }
148

149
        return $yaml;
1✔
150
    }
151

152
    private function createMapper(): Valinor\Mapper\TreeMapper
17✔
153
    {
154
        $presetFactory = new Preset\PresetFactory();
17✔
155

156
        return (new Valinor\MapperBuilder())
17✔
157
            ->registerConstructor(
17✔
158
                $presetFactory->get(...),
17✔
159
                static fn (string $name): Preset\Preset => $presetFactory->get($name),
17✔
160
            )
17✔
161
            ->allowPermissiveTypes()
17✔
162
            ->mapper()
17✔
163
        ;
17✔
164
    }
165
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc