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

move-elevator / composer-translation-validator / 16524379900

25 Jul 2025 02:25PM UTC coverage: 95.53% (-0.9%) from 96.456%
16524379900

Pull #46

github

jackd248
fix: add newline at end of unsupported.txt
Pull Request #46: feat: add KeyNamingConventionValidator with configurable naming conventions

256 of 285 new or added lines in 12 files covered. (89.82%)

2116 of 2215 relevant lines covered (95.53%)

8.09 hits per line

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

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

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the Composer plugin "composer-translation-validator".
7
 *
8
 * Copyright (C) 2025 Konrad Michalik <km@move-elevator.de>
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 MoveElevator\ComposerTranslationValidator\Result;
25

26
use MoveElevator\ComposerTranslationValidator\Config\TranslationValidatorConfig;
27
use MoveElevator\ComposerTranslationValidator\FileDetector\FileSet;
28
use MoveElevator\ComposerTranslationValidator\Parser\ParserCache;
29
use MoveElevator\ComposerTranslationValidator\Validator\ResultType;
30
use MoveElevator\ComposerTranslationValidator\Validator\ValidatorInterface;
31
use Psr\Log\LoggerInterface;
32
use Throwable;
33

34
class ValidationRun
35
{
36
    public function __construct(
11✔
37
        private readonly LoggerInterface $logger,
38
    ) {}
11✔
39

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

52
        foreach ($fileSets as $fileSet) {
11✔
53
            $filesChecked += count($fileSet->getFiles());
8✔
54
            foreach ($validatorClasses as $validatorClass) {
8✔
55
                // Create a new validator instance for each FileSet to ensure isolation
56
                $validatorInstance = new $validatorClass($this->logger);
7✔
57

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

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

77
        $keysChecked = $this->countKeysChecked($fileSets);
11✔
78

79
        $validatorsRun = count($validatorClasses);
11✔
80

81
        // Get cache statistics before clearing cache
82
        $cacheStats = ParserCache::getCacheStats();
11✔
83
        $parsersCached = $cacheStats['cached_parsers'];
11✔
84

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

94
        $validationResult = new ValidationResult($validatorInstances, $overallResult, $validatorFileSetPairs, $statistics);
11✔
95
        ParserCache::clear();
11✔
96

97
        return $validationResult;
11✔
98
    }
99

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

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

117
        return $fileSets;
4✔
118
    }
119

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

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

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

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