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

move-elevator / composer-translation-validator / 16137064113

08 Jul 2025 07:41AM UTC coverage: 78.302% (-16.2%) from 94.526%
16137064113

Pull #19

github

web-flow
Merge 5f8b3255c into 3e904fb25
Pull Request #19: refactor: improve output style

93 of 278 new or added lines in 7 files covered. (33.45%)

103 existing lines in 7 files now uncovered.

830 of 1060 relevant lines covered (78.3%)

4.18 hits per line

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

69.23
/src/Validator/SchemaValidator.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace MoveElevator\ComposerTranslationValidator\Validator;
6

7
use MoveElevator\ComposerTranslationValidator\Parser\ParserInterface;
8
use MoveElevator\ComposerTranslationValidator\Parser\XliffParser;
9
use MoveElevator\ComposerTranslationValidator\Result\Issue;
10
use Symfony\Component\Config\Util\XmlUtils;
11
use Symfony\Component\Console\Helper\Table;
12
use Symfony\Component\Console\Helper\TableSeparator;
13
use Symfony\Component\Console\Helper\TableStyle;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Translation\Util\XliffUtils;
17

18
class SchemaValidator extends AbstractValidator implements ValidatorInterface
19
{
20
    public function processFile(ParserInterface $file): array
3✔
21
    {
22
        try {
23
            /*
24
             * With XmlUtils::loadFile() we always get a strange symfony error related to global composer autoloading issue.
25
             *      Call to undefined method Symfony\Component\Filesystem\Filesystem::readFile()
26
             */
27
            if (!file_exists($file->getFilePath())) {
3✔
28
                $this->logger?->error('File does not exist: '.$file->getFileName());
1✔
29

30
                return [];
1✔
31
            }
32

33
            $fileContent = file_get_contents($file->getFilePath());
2✔
34
            if (false === $fileContent) {
2✔
UNCOV
35
                $this->logger?->error('Failed to read file: '.$file->getFileName());
×
36

37
                return [];
×
38
            }
39
            $dom = XmlUtils::parse($fileContent);
2✔
40
            $errors = XliffUtils::validateSchema($dom);
2✔
UNCOV
41
        } catch (\Exception $e) {
×
UNCOV
42
            $this->logger?->error('Failed to validate XML schema: '.$e->getMessage());
×
43

UNCOV
44
            return [];
×
45
        }
46

47
        if (!empty($errors)) {
2✔
48
            return $errors;
1✔
49
        }
50

51
        return [];
1✔
52
    }
53

54
    /**
55
     * @param array<string, array<int, array{
56
     *     file: string,
57
     *     issues: array<int, array{
58
     *         level: string,
59
     *         code: int,
60
     *         message: string,
61
     *         file: string,
62
     *         line: int,
63
     *         column: int
64
     *     }>,
65
     *     parser: string,
66
     *     type: string
67
     * }>> $issueSets
68
     */
69
    public function renderIssueSets(InputInterface $input, OutputInterface $output, array $issueSets): void
1✔
70
    {
71
        $currentFile = null;
1✔
72
        $table = new Table($output);
1✔
73
        $table
1✔
74
            ->setHeaders(['File', 'Level', 'Code', 'Message', 'Line'])
1✔
75
            ->setStyle(
1✔
76
                (new TableStyle())
1✔
77
                    ->setCellHeaderFormat('%s')
1✔
78
            );
1✔
79

80
        foreach ($issueSets as $issues) {
1✔
81
            foreach ($issues as $errors) {
1✔
82
                if ($currentFile !== $errors['file'] && null !== $currentFile) {
1✔
83
                    $table->addRow(new TableSeparator());
1✔
84
                }
85
                $currentFile = $errors['file'];
1✔
86

87
                foreach ($errors['issues'] as $error) {
1✔
88
                    $message = preg_replace(
1✔
89
                        "/^Element ('(?:\{[^}]+\})?[^']+'):?\s*/",
1✔
90
                        '',
1✔
91
                        (string) $error['message']
1✔
92
                    );
1✔
93

94
                    $table->addRow([
1✔
95
                        '<fg=red>'.$errors['file'].'</>',
1✔
96
                        LIBXML_ERR_WARNING === (int) $error['level'] ? 'Warning' : 'Error',
1✔
97
                        $error['code'],
1✔
98
                        trim((string) $message),
1✔
99
                        $error['line'],
1✔
100
                    ]);
1✔
101
                    $errors['file'] = ''; // Reset file for subsequent rows
1✔
102
                }
103
            }
104
        }
105
        $table->render();
1✔
106
    }
107

108
    public function explain(): string
1✔
109
    {
110
        return 'Validates the XML schema of translation files against the XLIFF standard. '.
1✔
111
            'This ensures that the files are well-formed and adhere to the expected structure.';
1✔
112
    }
113

114
    /**
115
     * @return class-string<ParserInterface>[]
116
     */
117
    public function supportsParser(): array
1✔
118
    {
119
        return [XliffParser::class];
1✔
120
    }
121

NEW
UNCOV
122
    public function formatIssueMessage(Issue $issue, string $prefix = '', bool $isVerbose = false): string
×
123
    {
NEW
UNCOV
124
        $details = $issue->getDetails();
×
NEW
UNCOV
125
        $messages = [];
×
126

NEW
UNCOV
127
        foreach ($details as $error) {
×
NEW
UNCOV
128
            if (is_array($error)) {
×
NEW
UNCOV
129
                $message = $error['message'] ?? 'Schema validation error';
×
NEW
UNCOV
130
                $line = isset($error['line']) ? " (Line: {$error['line']})" : '';
×
NEW
UNCOV
131
                $code = isset($error['code']) ? " (Code: {$error['code']})" : '';
×
NEW
UNCOV
132
                $level = $error['level'] ?? 'ERROR';
×
133

NEW
UNCOV
134
                $color = 'ERROR' === strtoupper($level) ? 'red' : 'yellow';
×
NEW
UNCOV
135
                $levelText = ucfirst(strtolower($level));
×
136

NEW
UNCOV
137
                $messages[] = "- <fg=$color>$levelText</> {$prefix}$message$line$code";
×
138
            }
139
        }
140

NEW
UNCOV
141
        if (empty($messages)) {
×
NEW
UNCOV
142
            $messages[] = "- <fg=red>Error</> {$prefix}Schema validation error";
×
143
        }
144

NEW
UNCOV
145
        return implode("\n", $messages);
×
146
    }
147
}
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

© 2026 Coveralls, Inc