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

move-elevator / composer-translation-validator / 16588667316

29 Jul 2025 06:40AM UTC coverage: 96.242% (-0.4%) from 96.609%
16588667316

Pull #59

github

jackd248
refactor: streamline constructor syntax and improve property visibility in configuration classes
Pull Request #59: refactor: domain architecture

119 of 132 new or added lines in 10 files covered. (90.15%)

3 existing lines in 1 file now uncovered.

2356 of 2448 relevant lines covered (96.24%)

8.19 hits per line

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

93.22
/src/Validation/ValidationEngine.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\Validation;
25

26
use InvalidArgumentException;
27
use MoveElevator\ComposerTranslationValidator\Config\TranslationValidatorConfig;
28
use MoveElevator\ComposerTranslationValidator\Result\ValidationResult;
29
use MoveElevator\ComposerTranslationValidator\Service\ValidationOrchestrationService;
30
use MoveElevator\ComposerTranslationValidator\Validator\ValidatorRegistry;
31
use Psr\Log\LoggerInterface;
32
use RuntimeException;
33
use Throwable;
34

35
/**
36
 * Main API implementation for programmatic translation validation.
37
 *
38
 * This class provides the primary entry point for external packages
39
 * to validate translation files programmatically.
40
 */
41
final class ValidationEngine implements ValidationEngineInterface
42
{
43
    public function __construct(private readonly ValidationOrchestrationService $orchestrationService, private readonly LoggerInterface $logger)
15✔
44
    {
45
    }
15✔
46

47
    public function validatePaths(array $paths, array $options = []): ?ValidationResult
11✔
48
    {
49
        if (empty($paths)) {
11✔
50
            throw new InvalidArgumentException('Paths array cannot be empty');
1✔
51
        }
52

53
        $validationOptions = ValidationOptions::fromArray($options);
10✔
54
        $config = $this->createConfigFromOptions($validationOptions);
10✔
55

56
        // Resolve absolute paths
57
        $absolutePaths = $this->orchestrationService->resolvePaths($paths, $config);
10✔
58

59
        // Resolve file detector
60
        $fileDetector = $this->orchestrationService->resolveFileDetector($config);
10✔
61

62
        // Resolve validators
63
        $validators = $this->orchestrationService->resolveValidators(
10✔
64
            $validationOptions->onlyValidators,
10✔
65
            $validationOptions->skipValidators,
10✔
66
            $config,
10✔
67
        );
10✔
68

69
        try {
70
            return $this->orchestrationService->executeValidation(
10✔
71
                $absolutePaths,
10✔
72
                $validationOptions->excludePatterns,
10✔
73
                $validationOptions->recursive,
10✔
74
                $fileDetector,
10✔
75
                $validators,
10✔
76
                $config,
10✔
77
            );
10✔
78
        } catch (Throwable $e) {
1✔
79
            $this->logger->error('Validation execution failed', [
1✔
80
                'error' => $e->getMessage(),
1✔
81
                'paths' => $paths,
1✔
82
                'options' => $options,
1✔
83
            ]);
1✔
84
            throw new RuntimeException(sprintf('Validation failed: %s', $e->getMessage()), 0, $e);
1✔
85
        }
86
    }
87

88
    public function validateProject(string $projectPath, array $configuration = []): ?ValidationResult
5✔
89
    {
90
        if (empty($projectPath)) {
5✔
91
            throw new InvalidArgumentException('Project path cannot be empty');
1✔
92
        }
93

94
        if (!is_dir($projectPath)) {
4✔
95
            throw new InvalidArgumentException(sprintf('Project path "%s" is not a valid directory', $projectPath));
1✔
96
        }
97

98
        // Use project path as single path to validate
99
        $paths = [rtrim($projectPath, '/')];
3✔
100

101
        // Enable recursive by default for project validation
102
        $options = array_merge(['recursive' => true], $configuration);
3✔
103

104
        return $this->validatePaths($paths, $options);
3✔
105
    }
106

107
    public function getAvailableValidators(): array
2✔
108
    {
109
        return ValidatorRegistry::getAvailableValidators();
2✔
110
    }
111

112
    public function isReady(): bool
1✔
113
    {
114
        try {
115
            // Check if we have validators available
116
            $validators = $this->getAvailableValidators();
1✔
117
            if (empty($validators)) {
1✔
NEW
118
                return false;
×
119
            }
120

121
            // Basic readiness checks passed
122

123
            return true;
1✔
NEW
124
        } catch (Throwable) {
×
NEW
125
            return false;
×
126
        }
127
    }
128

129
    /**
130
     * Create configuration from validation options.
131
     */
132
    private function createConfigFromOptions(ValidationOptions $options): TranslationValidatorConfig
10✔
133
    {
134
        $config = new TranslationValidatorConfig();
10✔
135

136
        if (!empty($options->onlyValidators)) {
10✔
137
            $config->setOnly($options->onlyValidators);
1✔
138
        }
139

140
        if (!empty($options->skipValidators)) {
10✔
141
            $config->setSkip($options->skipValidators);
1✔
142
        }
143

144
        if (!empty($options->excludePatterns)) {
10✔
145
            $config->setExclude($options->excludePatterns);
1✔
146
        }
147

148
        if (null !== $options->fileDetector) {
10✔
NEW
149
            $config->setFileDetectors([$options->fileDetector]);
×
150
        }
151

152
        $config->setDryRun($options->dryRun);
10✔
153
        $config->setStrict($options->strict);
10✔
154

155
        return $config;
10✔
156
    }
157
}
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