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

move-elevator / composer-translation-validator / 24129407734

08 Apr 2026 09:55AM UTC coverage: 95.378% (-0.1%) from 95.491%
24129407734

Pull #112

github

konradmichalik
fix: apply rector migrations
Pull Request #112: refactor: replace static ParserCache with constructor injection

17 of 20 new or added lines in 3 files covered. (85.0%)

15 existing lines in 2 files now uncovered.

2373 of 2488 relevant lines covered (95.38%)

8.12 hits per line

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

94.92
/src/Result/ValidationRun.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the "composer-translation-validator" Composer plugin.
7
 *
8
 * (c) 2025-2026 Konrad Michalik <km@move-elevator.de>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13

14
namespace MoveElevator\ComposerTranslationValidator\Result;
15

16
use MoveElevator\ComposerTranslationValidator\Config\TranslationValidatorConfig;
17
use MoveElevator\ComposerTranslationValidator\FileDetector\FileSet;
18
use MoveElevator\ComposerTranslationValidator\Parser\ParserCache;
19
use MoveElevator\ComposerTranslationValidator\Validator\{ResultType, ValidatorInterface};
20
use Psr\Log\LoggerInterface;
21
use Throwable;
22

23
use function count;
24
use function is_array;
25

26
/**
27
 * ValidationRun.
28
 *
29
 * @author Konrad Michalik <km@move-elevator.de>
30
 * @license GPL-3.0-or-later
31
 */
32
class ValidationRun
33
{
34
    public function __construct(private readonly LoggerInterface $logger, private readonly ?ParserCache $parserCache = new ParserCache()) {}
8✔
35

36
    /**
37
     * @param array<FileSet>                          $fileSets
38
     * @param array<class-string<ValidatorInterface>> $validatorClasses
39
     */
40
    public function executeFor(array $fileSets, array $validatorClasses, ?TranslationValidatorConfig $config = null): ValidationResult
8✔
41
    {
42
        $startTime = microtime(true);
8✔
43
        $validatorInstances = [];
8✔
44
        $validatorFileSetPairs = [];
8✔
45
        $overallResult = ResultType::SUCCESS;
8✔
46
        $filesChecked = 0;
8✔
47

48
        foreach ($fileSets as $fileSet) {
8✔
49
            $filesChecked += count($fileSet->getFiles());
6✔
50
            foreach ($validatorClasses as $validatorClass) {
6✔
51
                // Create a new validator instance for each FileSet to ensure isolation
52
                $validatorInstance = new $validatorClass($this->logger);
5✔
53

54
                // Share the ParserCache instance across all validators
55
                if (method_exists($validatorInstance, 'setParserCache')) {
5✔
NEW
UNCOV
56
                    $validatorInstance->setParserCache($this->parserCache);
×
57
                }
58

59
                // Pass config to validator if it supports it
60
                if (null !== $config && method_exists($validatorInstance, 'setConfig')) {
5✔
61
                    $validatorInstance->setConfig($config);
×
62
                }
63

64
                /** @var class-string<\MoveElevator\ComposerTranslationValidator\Parser\ParserInterface> $parserClass */
65
                $parserClass = $fileSet->getParser();
5✔
66
                $result = $validatorInstance->validate($fileSet->getFiles(), $parserClass);
5✔
67
                if (!empty($result)) {
5✔
68
                    $overallResult = $overallResult->max($validatorInstance->resultTypeOnValidationFailure());
4✔
69
                    $validatorInstances[] = $validatorInstance;
4✔
70
                    $validatorFileSetPairs[] = [
4✔
71
                        'validator' => $validatorInstance,
4✔
72
                        'fileSet' => $fileSet,
4✔
73
                    ];
4✔
74
                }
75
            }
76
        }
77

78
        $keysChecked = $this->countKeysChecked($fileSets);
8✔
79

80
        $validatorsRun = count($validatorClasses);
8✔
81

82
        // Get cache statistics before clearing cache
83
        $cacheStats = $this->parserCache->getCacheStats();
8✔
84
        $parsersCached = $cacheStats['cached_parsers'];
8✔
85

86
        $executionTime = microtime(true) - $startTime;
8✔
87
        $statistics = new ValidationStatistics(
8✔
88
            $executionTime,
8✔
89
            $filesChecked,
8✔
90
            $keysChecked,
8✔
91
            $validatorsRun,
8✔
92
            $parsersCached,
8✔
93
        );
8✔
94

95
        $validationResult = new ValidationResult($validatorInstances, $overallResult, $validatorFileSetPairs, $statistics);
8✔
96
        $this->parserCache->clear();
8✔
97

98
        return $validationResult;
8✔
99
    }
100

101
    /**
102
     * @param array<string, array<string, array<string, array<string>>>> $allFiles
103
     *
104
     * @return array<FileSet>
105
     */
106
    public static function createFileSetsFromArray(array $allFiles): array
3✔
107
    {
108
        $fileSets = [];
3✔
109

110
        foreach ($allFiles as $parser => $paths) {
3✔
111
            foreach ($paths as $path => $translationSets) {
2✔
112
                foreach ($translationSets as $setKey => $files) {
2✔
113
                    $fileSets[] = new FileSet($parser, $path, $setKey, $files);
2✔
114
                }
115
            }
116
        }
117

118
        return $fileSets;
3✔
119
    }
120

121
    /**
122
     * @param array<FileSet> $fileSets
123
     */
124
    private function countKeysChecked(array $fileSets): int
8✔
125
    {
126
        $keysChecked = 0;
8✔
127

128
        foreach ($fileSets as $fileSet) {
8✔
129
            $parserClass = $fileSet->getParser();
6✔
130

131
            foreach ($fileSet->getFiles() as $file) {
6✔
132
                try {
133
                    $parser = $this->parserCache->get($file, $parserClass);
6✔
134
                    if (false === $parser) {
2✔
UNCOV
135
                        continue;
×
136
                    }
137
                    $keys = $parser->extractKeys();
2✔
138
                    if (is_array($keys)) {
2✔
139
                        $keysChecked += count($keys);
2✔
140
                    }
141
                } catch (Throwable) {
4✔
142
                    // Skip files that can't be parsed
143
                }
144
            }
145
        }
146

147
        return $keysChecked;
8✔
148
    }
149
}
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