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

eliashaeussler / version-bumper / 26332173808

23 May 2026 12:03PM UTC coverage: 89.113% (+0.5%) from 88.618%
26332173808

push

github

web-flow
Merge pull request #145 from eliashaeussler/feature/glob

[FEATURE] Support wildcards in path of files to modify

33 of 35 new or added lines in 1 file covered. (94.29%)

1236 of 1387 relevant lines covered (89.11%)

5.3 hits per line

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

85.71
/src/Config/VersionBumperConfig.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-2026 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 EliasHaeussler\VersionBumper\Version;
27
use ReflectionObject;
28
use Symfony\Component\Filesystem;
29

30
use function array_merge;
31
use function is_array;
32

33
/**
34
 * VersionBumperConfig.
35
 *
36
 * @author Elias Häußler <elias@haeussler.dev>
37
 * @license GPL-3.0-or-later
38
 */
39
final class VersionBumperConfig
40
{
41
    /**
42
     * @param list<Preset\Preset>         $presets
43
     * @param list<FileToModify>          $filesToModify
44
     * @param list<VersionRangeIndicator> $versionRangeIndicators
45
     */
46
    public function __construct(
7✔
47
        private readonly array $presets = [],
48
        private array $filesToModify = [],
49
        private ?string $rootPath = null,
50
        private readonly ReleaseOptions $releaseOptions = new ReleaseOptions(),
51
        private readonly array $versionRangeIndicators = [],
52
    ) {
53
        $this->resolveWildcardsInFiles();
7✔
54
    }
55

56
    /**
57
     * @return list<Preset\Preset>
58
     */
59
    public function presets(): array
×
60
    {
61
        return $this->presets;
×
62
    }
63

64
    /**
65
     * @return list<FileToModify>
66
     */
67
    public function filesToModify(): array
3✔
68
    {
69
        return $this->filesToModify;
3✔
70
    }
71

72
    public function hasActions(Version\Action\ActionType $type): bool
1✔
73
    {
74
        foreach ($this->filesToModify as $fileToModify) {
1✔
75
            if ([] !== $fileToModify->getActionsByType($type)) {
1✔
76
                return true;
1✔
77
            }
78
        }
79

80
        return false;
1✔
81
    }
82

83
    public function rootPath(): ?string
×
84
    {
85
        return $this->rootPath;
×
86
    }
87

88
    public function setRootPath(string $rootPath): self
1✔
89
    {
90
        $previousRootPath = $this->rootPath;
1✔
91

92
        $this->rootPath = $rootPath;
1✔
93

94
        if ($previousRootPath !== $rootPath) {
1✔
95
            $this->resolveWildcardsInFiles();
1✔
96
        }
97

98
        return $this;
1✔
99
    }
100

101
    public function releaseOptions(): ReleaseOptions
×
102
    {
103
        return $this->releaseOptions;
×
104
    }
105

106
    /**
107
     * @return list<VersionRangeIndicator>
108
     */
109
    public function versionRangeIndicators(): array
×
110
    {
111
        return $this->versionRangeIndicators;
×
112
    }
113

114
    /**
115
     * @impure
116
     *
117
     * @internal
118
     */
119
    public function merge(self $other): self
3✔
120
    {
121
        $shell = new self();
3✔
122
        $reflection = new ReflectionObject($other);
3✔
123
        $parameters = $reflection->getConstructor()?->getParameters() ?? [];
3✔
124
        $properties = [];
3✔
125

126
        foreach ($parameters as $parameter) {
3✔
127
            $property = $reflection->getProperty($parameter->getName());
3✔
128
            $thisValue = $property->getValue($this);
3✔
129
            $otherValue = $property->getValue($other);
3✔
130

131
            /* @phpstan-ignore notEqual.notAllowed (Loose comparison is intended as we compare objects) */
132
            if ($property->getValue($shell) != $otherValue) {
3✔
133
                $thisValue = is_array($thisValue) && is_array($otherValue)
2✔
134
                    ? array_merge($thisValue, $otherValue)
1✔
135
                    : $otherValue
1✔
136
                ;
2✔
137
            }
138

139
            $properties[] = $thisValue;
3✔
140
        }
141

142
        /* @phpstan-ignore argument.type */
143
        return new self(...$properties);
3✔
144
    }
145

146
    private function resolveWildcardsInFiles(): void
7✔
147
    {
148
        $modified = false;
7✔
149
        $filesToModify = [];
7✔
150

151
        foreach ($this->filesToModify as $fileToModify) {
7✔
152
            $path = $fileToModify->path();
7✔
153

154
            // Skip files without wildcards
155
            if (!str_contains($path, '*')) {
7✔
156
                $filesToModify[] = $fileToModify;
3✔
157

158
                continue;
3✔
159
            }
160

161
            $isRelative = Filesystem\Path::isRelative($path);
7✔
162

163
            if ($isRelative) {
7✔
164
                // We cannot process relative paths if root path is not set
165
                if (null === $this->rootPath) {
7✔
166
                    $filesToModify[] = $fileToModify;
7✔
167

168
                    continue;
7✔
169
                }
170

171
                $fullPath = $fileToModify->fullPath($this->rootPath);
3✔
172
            } else {
173
                $fullPath = $path;
7✔
174
            }
175

176
            $files = glob($fullPath);
7✔
177

178
            // Skip wildcard resolution if glob fails
179
            if (false === $files) {
7✔
NEW
180
                $filesToModify[] = $fileToModify;
×
181

NEW
182
                continue;
×
183
            }
184

185
            foreach ($files as $file) {
7✔
186
                $filesToModify[] = new FileToModify(
7✔
187
                    $isRelative ? Filesystem\Path::makeRelative($file, $this->rootPath) : $file,
7✔
188
                    $fileToModify->patterns(),
7✔
189
                    $fileToModify->reportUnmatched(),
7✔
190
                    $fileToModify->reportMissing(),
7✔
191
                    $fileToModify->preActions(),
7✔
192
                    $fileToModify->postActions(),
7✔
193
                );
7✔
194
            }
195

196
            $modified = true;
7✔
197
        }
198

199
        if ($modified) {
7✔
200
            $this->filesToModify = $filesToModify;
7✔
201
        }
202
    }
203
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc