Conversation
WalkthroughThis update introduces a comprehensive test suite with fixtures, configuration, and workflow for static analysis and code coverage. It refactors parser and validator resolution logic, removes the Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ConsoleApp
participant ValidateTranslationCommand
participant Collector
participant ParserRegistry
participant Parser
participant ValidatorRegistry
participant Validator
User->>ConsoleApp: Run validate-translation command
ConsoleApp->>ValidateTranslationCommand: Execute
ValidateTranslationCommand->>Collector: collectFiles(paths)
Collector->>ParserRegistry: getAvailableParsers()
Collector->>ParserRegistry: resolveParserClass(filePath)
Collector->>Parser: getSupportedFileExtensions()
Collector-->>ValidateTranslationCommand: grouped files by parser
ValidateTranslationCommand->>ValidatorRegistry: getAvailableValidators()
ValidateTranslationCommand->>Validator: validate(files, parserClass)
Validator->>Parser: parse files
Validator-->>ValidateTranslationCommand: validation results
ValidateTranslationCommand-->>ConsoleApp: Output results
Possibly related PRs
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 phpcs (3.7.2)src/Command/ValidateTranslationCommand.phpWarning: PHP Startup: Invalid date.timezone value 'UTC', using 'UTC' instead in Unknown on line 0 Fatal error: Uncaught Error: Class "Phar" not found in /usr/local/bin/phpcs:3 ✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 0
🔭 Outside diff range comments (1)
composer.json (1)
25-25: Address dependency version conflict causing pipeline failure.The
armin/editorconfig-clidependency requires PHP ^8.2, but the CI is running PHP 8.1.32, causing composer update failures.#!/bin/bash # Check if armin/editorconfig-cli has versions compatible with PHP 8.1 curl -s https://packagist.org/packages/armin/editorconfig-cli.json | jq '.package.versions | to_entries[] | select(.value.require.php) | {version: .key, php: .value.require.php}'Consider either:
- Updating the minimum PHP version requirement to 8.2
- Finding a compatible version of
armin/editorconfig-cli- Using an alternative editorconfig tool
♻️ Duplicate comments (1)
tests/src/Fixtures/translations/xliff/success/de.locallang.xlf (1)
6-13: Same concern as French fixture regarding empty source elements.This fixture has the same structure as
fr.locallang.xlfwith empty<source/>elements. Please confirm if this is intentional for testing purposes.
🧹 Nitpick comments (5)
src/Utility/PathUtility.php (1)
22-22: Consider edge case: getcwd() can return false.While unlikely in normal operation,
getcwd()can returnfalsein certain scenarios (e.g., if the current directory has been deleted). Consider adding a check to handle this edge case gracefully.- $cwd = realpath(getcwd()).DIRECTORY_SEPARATOR; + $currentDir = getcwd(); + if (false === $currentDir) { + return $normalizedPath; + } + $cwd = realpath($currentDir).DIRECTORY_SEPARATOR;tests/Build/console-application.php (1)
1-12: Consider adding a file doc comment to address static analysis warning.The code logic is correct and serves its purpose well for test infrastructure. However, phpcs flagged a missing file doc comment.
Consider adding a file doc comment:
<?php + +/** + * Console application setup for testing ValidateTranslationCommand. + */ declare(strict_types=1);tests/src/Validator/MismatchValidatorTest.php (2)
15-44: Add missing import for ReflectionClass.The test logic is well-structured and correctly verifies the
processFilemethod behavior. However, there's a missing import statement for theReflectionClassused in the test.+use ReflectionClass;Add this import at the top of the file with other use statements.
128-160: Add missing import and fix output assertion.The test logic is correct for validating console output rendering, but there are a couple of issues:
+use Symfony\Component\Console\Output\BufferedOutput;Also, the current assertion uses
assertStringContainsStringbut should useassertSamefor exact output matching:- $this->assertStringContainsString(trim($expectedOutput), trim($output->fetch())); + $this->assertSame(trim($expectedOutput), trim($output->fetch()));tests/src/Parser/XliffParserTest.php (1)
84-110: LGTM - Thorough constructor validation tests.The tests effectively validate input parameters with appropriate exception handling. Note that the unreadable file test may need cleanup to restore permissions if the test fails unexpectedly.
Consider adding permission restoration in the tearDown method:
protected function tearDown(): void { parent::tearDown(); if (is_dir($this->tempDir)) { + // Restore permissions before cleanup + $this->restorePermissions($this->tempDir); $this->removeDirectory($this->tempDir); } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (36)
.github/workflows/ci.yml(1 hunks).php-cs-fixer.php(1 hunks)composer.json(2 hunks)phpstan.neon(1 hunks)phpunit.xml(1 hunks)rector.php(1 hunks)src/Command/ValidateTranslationCommand.php(0 hunks)src/FileDetector/Collector.php(1 hunks)src/Parser/ParserUtility.php(2 hunks)src/Parser/XliffParser.php(1 hunks)src/Utility/PathUtility.php(1 hunks)tests/Build/console-application.php(1 hunks)tests/src/Capability/ValidateTranslationCommandProviderTest.php(1 hunks)tests/src/Command/ValidateTranslationCommandTest.php(1 hunks)tests/src/FileDetector/CollectorTest.php(1 hunks)tests/src/FileDetector/PrefixFileDetectorTest.php(1 hunks)tests/src/Fixtures/translations/xliff/fail/de.locallang.xlf(1 hunks)tests/src/Fixtures/translations/xliff/fail/de.locallang_be.xlf(1 hunks)tests/src/Fixtures/translations/xliff/fail/locallang.xlf(1 hunks)tests/src/Fixtures/translations/xliff/fail/locallang_be.xlf(1 hunks)tests/src/Fixtures/translations/xliff/success/de.locallang.xlf(1 hunks)tests/src/Fixtures/translations/xliff/success/de.locallang_be.xlf(1 hunks)tests/src/Fixtures/translations/xliff/success/fr.locallang.xlf(1 hunks)tests/src/Fixtures/translations/xliff/success/locallang.xlf(1 hunks)tests/src/Fixtures/translations/xliff/success/locallang_be.xlf(1 hunks)tests/src/Parser/ParserRegistryTest.php(1 hunks)tests/src/Parser/ParserUtilityTest.php(1 hunks)tests/src/Parser/XliffParserTest.php(1 hunks)tests/src/PluginTest.php(1 hunks)tests/src/Utility/ClassUtilityTest.php(1 hunks)tests/src/Utility/OutputUtilityTest.php(1 hunks)tests/src/Utility/PathUtilityTest.php(1 hunks)tests/src/Validator/DuplicatesValidatorTest.php(1 hunks)tests/src/Validator/MismatchValidatorTest.php(1 hunks)tests/src/Validator/SchemaValidatorTest.php(1 hunks)tests/src/Validator/ValidatorRegistryTest.php(1 hunks)
💤 Files with no reviewable changes (1)
- src/Command/ValidateTranslationCommand.php
🧰 Additional context used
🧬 Code Graph Analysis (7)
src/Parser/ParserUtility.php (3)
src/Parser/ParserRegistry.php (2)
ParserRegistry(7-18)getAvailableParsers(12-17)src/Parser/XliffParser.php (1)
getSupportedFileExtensions(60-63)src/Parser/ParserInterface.php (1)
getSupportedFileExtensions(14-14)
tests/src/Validator/ValidatorRegistryTest.php (1)
src/Validator/ValidatorRegistry.php (2)
ValidatorRegistry(7-20)getAvailableValidators(12-19)
tests/src/PluginTest.php (2)
src/Plugin.php (2)
Plugin(14-34)getCapabilities(28-33)src/Capability/ValidateTranslationCommandProvider.php (1)
ValidateTranslationCommandProvider(10-18)
tests/src/Parser/ParserRegistryTest.php (2)
src/Parser/ParserRegistry.php (2)
ParserRegistry(7-18)getAvailableParsers(12-17)src/Parser/XliffParser.php (1)
XliffParser(11-98)
tests/src/FileDetector/PrefixFileDetectorTest.php (1)
src/FileDetector/PrefixFileDetector.php (1)
PrefixFileDetector(7-26)
tests/src/Utility/OutputUtilityTest.php (1)
src/Utility/OutputUtility.php (2)
OutputUtility(9-27)debug(11-26)
src/FileDetector/Collector.php (2)
src/Parser/ParserInterface.php (1)
getSupportedFileExtensions(14-14)src/FileDetector/PrefixFileDetector.php (1)
mapTranslationSet(14-25)
🪛 phpcs (3.7.2)
tests/src/Capability/ValidateTranslationCommandProviderTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 11-11: Missing doc comment for class ValidateTranslationCommandProviderTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 13-13: Missing doc comment for function testGetCommands()
(PEAR.Commenting.FunctionComment.Missing)
tests/Build/console-application.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
tests/src/Validator/ValidatorRegistryTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 13-13: Missing doc comment for class ValidatorRegistryTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 15-15: Missing doc comment for function testGetAvailableValidators()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/PluginTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 12-12: Missing doc comment for class PluginTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 14-14: Missing doc comment for function testGetCapabilities()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Parser/ParserRegistryTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 11-11: Missing doc comment for class ParserRegistryTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 13-13: Missing doc comment for function testGetAvailableParsers()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/FileDetector/PrefixFileDetectorTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 10-10: Missing doc comment for class PrefixFileDetectorTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 12-12: Missing doc comment for function testMapTranslationSetWithPrefixedFiles()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 32-32: Missing doc comment for function testMapTranslationSetWithMixedFiles()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 56-56: Missing doc comment for function testMapTranslationSetWithNoPrefixedFiles()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 76-76: Missing doc comment for function testMapTranslationSetWithEmptyArray()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/FileDetector/CollectorTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 13-13: Missing doc comment for class CollectorTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 15-15: Private member variable "tempDir" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 17-17: Missing doc comment for function setUp()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 24-24: Missing doc comment for function tearDown()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 32-32: Missing doc comment for function removeDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 32-32: Private method name "CollectorTest::removeDirectory" must be prefixed with an underscore
(PEAR.NamingConventions.ValidFunctionName.PrivateNoUnderscore)
[ERROR] 41-41: Missing doc comment for function testCollectFilesWithValidPath()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 58-58: Missing doc comment for function testCollectFilesWithInvalidPath()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 73-73: Missing doc comment for function testCollectFilesWithExcludedFiles()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 91-91: Missing doc comment for function testCollectFilesWithNoMatchingFiles()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Validator/DuplicatesValidatorTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 13-13: Missing doc comment for class DuplicatesValidatorTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 15-15: Missing doc comment for function testProcessFileWithDuplicates()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 30-30: Missing doc comment for function testProcessFileWithoutDuplicates()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 45-45: Missing doc comment for function testProcessFileWithInvalidFile()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 62-62: Missing doc comment for function testRenderIssueSets()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 99-99: Missing doc comment for function testExplain()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Parser/ParserUtilityTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 11-11: Missing doc comment for class ParserUtilityTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 13-13: Missing doc comment for function testResolveAllowedFileExtensions()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 22-22: Missing doc comment for function testResolveParserClasses()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 30-30: Missing doc comment for function testResolveParserClassWithSupportedExtension()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 43-43: Missing doc comment for function testResolveParserClassWithUnsupportedExtension()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Utility/OutputUtilityTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 11-11: Missing doc comment for class OutputUtilityTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 13-13: Missing doc comment for function testDebugWithVerboseOutput()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 25-25: Missing doc comment for function testDebugWithVeryVerboseOutput()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 37-37: Missing doc comment for function testDebugWithNonVerboseOutput()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 47-47: Missing doc comment for function testDebugWithNonVeryVerboseOutputAndVeryVerboseFlag()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 58-58: Missing doc comment for function testDebugWithNoNewLine()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Validator/MismatchValidatorTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 13-13: Missing doc comment for class MismatchValidatorTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 15-15: Missing doc comment for function testProcessFile()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 46-46: Missing doc comment for function testProcessFileWithInvalidFile()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 63-63: Missing doc comment for function testPostProcessWithMismatches()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 101-101: Missing doc comment for function testPostProcessWithoutMismatches()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 128-128: Missing doc comment for function testRenderIssueSets()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 162-162: Missing doc comment for function testExplain()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Utility/ClassUtilityTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 12-12: You must use "/**" style comments for a interface comment
(PEAR.Commenting.ClassComment.WrongStyle)
[ERROR] 15-15: Missing doc comment for class ValidClass
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 18-18: Missing doc comment for class InvalidClass
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 22-22: Missing doc comment for class ClassUtilityTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 24-24: Missing doc comment for function testValidateClassWithNullClass()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 32-32: Missing doc comment for function testValidateClassWithNonExistentClass()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 42-42: Missing doc comment for function testValidateClassWithClassNotImplementingInterface()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 52-52: Missing doc comment for function testValidateClassWithValidClass()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Validator/SchemaValidatorTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 14-14: Missing doc comment for class SchemaValidatorTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 16-16: Private member variable "tempDir" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 17-17: Private member variable "validXliffFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 18-18: Private member variable "invalidXliffFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 20-20: Missing doc comment for function setUp()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 27-27: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 43-43: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 59-59: Missing doc comment for function tearDown()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 67-67: Missing doc comment for function removeDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 67-67: Private method name "SchemaValidatorTest::removeDirectory" must be prefixed with an underscore
(PEAR.NamingConventions.ValidFunctionName.PrivateNoUnderscore)
[ERROR] 76-76: Missing doc comment for function testProcessFileWithValidXliff()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 90-90: Missing doc comment for function testProcessFileWithInvalidXliff()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 104-104: Missing doc comment for function testProcessFileWithNonExistentFile()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 120-120: Missing doc comment for function testRenderIssueSets()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 163-163: Missing doc comment for function testExplain()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Command/ValidateTranslationCommandTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 14-14: Missing doc comment for class ValidateTranslationCommandTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 16-16: Missing doc comment for function testExecuteWithValidArguments()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 24-24: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 27-27: Closing parenthesis of a multi-line function call must be on a line by itself
(PEAR.Functions.FunctionCallSignature.CloseBracketLine)
[ERROR] 34-34: Missing doc comment for function testExecuteWithNoPaths()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 42-42: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 44-44: Closing parenthesis of a multi-line function call must be on a line by itself
(PEAR.Functions.FunctionCallSignature.CloseBracketLine)
[ERROR] 50-50: Missing doc comment for function testExecuteWithNoFilesFound()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 58-58: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 60-60: Closing parenthesis of a multi-line function call must be on a line by itself
(PEAR.Functions.FunctionCallSignature.CloseBracketLine)
[ERROR] 66-66: Missing doc comment for function testExecuteWithInvalidValidator()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 74-74: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 77-77: Closing parenthesis of a multi-line function call must be on a line by itself
(PEAR.Functions.FunctionCallSignature.CloseBracketLine)
[ERROR] 83-83: Missing doc comment for function testExecuteWithErrors()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 91-91: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 93-93: Closing parenthesis of a multi-line function call must be on a line by itself
(PEAR.Functions.FunctionCallSignature.CloseBracketLine)
[ERROR] 99-99: Missing doc comment for function testExecuteWithErrorsAndDryRun()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 107-107: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 110-110: Closing parenthesis of a multi-line function call must be on a line by itself
(PEAR.Functions.FunctionCallSignature.CloseBracketLine)
tests/src/Utility/PathUtilityTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 10-10: Missing doc comment for class PathUtilityTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 12-12: Private member variable "originalCwd" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 13-13: Private member variable "tempDir" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 15-15: Missing doc comment for function setUp()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 23-23: Missing doc comment for function tearDown()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 32-32: Missing doc comment for function removeDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 32-32: Private method name "PathUtilityTest::removeDirectory" must be prefixed with an underscore
(PEAR.NamingConventions.ValidFunctionName.PrivateNoUnderscore)
[ERROR] 41-41: Missing doc comment for function testNormalizeFolderPathWithTrailingSlash()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 47-47: Missing doc comment for function testNormalizeFolderPathWithoutTrailingSlash()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 53-53: Missing doc comment for function testNormalizeFolderPathWithDotSlashPrefix()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 59-59: Missing doc comment for function testNormalizeFolderPathWithEmptyPath()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 65-65: Missing doc comment for function testNormalizeFolderPathWhenPathIsCwd()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 71-71: Missing doc comment for function testNormalizeFolderPathWhenPathIsSubdirectoryOfCwd()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 80-80: Missing doc comment for function testNormalizeFolderPathWhenPathIsNotRelatedToCwd()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Parser/XliffParserTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 13-13: Missing doc comment for class XliffParserTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 15-15: Private member variable "tempDir" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 16-16: Private member variable "validXliffFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 17-17: Private member variable "validXliffContent" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 39-39: Private member variable "prefixedXliffFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 40-40: Private member variable "prefixedXliffContent" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 54-54: Missing doc comment for function setUp()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 67-67: Missing doc comment for function tearDown()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 75-75: Missing doc comment for function removeDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 75-75: Private method name "XliffParserTest::removeDirectory" must be prefixed with an underscore
(PEAR.NamingConventions.ValidFunctionName.PrivateNoUnderscore)
[ERROR] 84-84: Missing doc comment for function testConstructorThrowsExceptionIfFileDoesNotExist()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 91-91: Missing doc comment for function testConstructorThrowsExceptionIfFileIsNotReadable()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 102-102: Missing doc comment for function testConstructorThrowsExceptionIfFileHasInvalidExtension()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 112-112: Missing doc comment for function testExtractKeys()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 120-120: Missing doc comment for function testGetContentByKeySource()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 130-130: Missing doc comment for function testGetContentByKeyTarget()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 140-140: Missing doc comment for function testGetSupportedFileExtensions()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 146-146: Missing doc comment for function testGetValidators()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 152-152: Missing doc comment for function testGetFileName()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 158-158: Missing doc comment for function testGetFileDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 164-164: Missing doc comment for function testGetFilePath()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 170-170: Missing doc comment for function testGetLanguageFromPrefixedFileName()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 176-176: Missing doc comment for function testGetLanguageFromSourceLanguageAttribute()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 182-182: Missing doc comment for function testGetLanguageWhenNoPrefixAndNoSourceLanguage()
(PEAR.Commenting.FunctionComment.Missing)
🪛 PHPMD (2.15.0)
src/Parser/ParserUtility.php
17-17: Avoid using static access to class 'MoveElevator\ComposerTranslationValidator\Parser\ParserRegistry' in method 'resolveAllowedFileExtensions'. (Clean Code Rules)
(StaticAccess)
52-52: Avoid using static access to class 'MoveElevator\ComposerTranslationValidator\Parser\ParserRegistry' in method 'resolveParserClass'. (Clean Code Rules)
(StaticAccess)
tests/src/Validator/ValidatorRegistryTest.php
17-17: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Validator\ValidatorRegistry' in method 'testGetAvailableValidators'. (Clean Code Rules)
(StaticAccess)
tests/src/Parser/ParserRegistryTest.php
15-15: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\ParserRegistry' in method 'testGetAvailableParsers'. (Clean Code Rules)
(StaticAccess)
tests/src/Validator/DuplicatesValidatorTest.php
65-65: Missing class import via use statement (line '65', column '23'). (Clean Code Rules)
(MissingImport)
tests/src/Parser/ParserUtilityTest.php
15-15: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\ParserUtility' in method 'testResolveAllowedFileExtensions'. (Clean Code Rules)
(StaticAccess)
24-24: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\ParserUtility' in method 'testResolveParserClasses'. (Clean Code Rules)
(StaticAccess)
33-33: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\ParserUtility' in method 'testResolveParserClassWithSupportedExtension'. (Clean Code Rules)
(StaticAccess)
38-38: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\ParserUtility' in method 'testResolveParserClassWithSupportedExtension'. (Clean Code Rules)
(StaticAccess)
46-46: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\ParserUtility' in method 'testResolveParserClassWithUnsupportedExtension'. (Clean Code Rules)
(StaticAccess)
tests/src/Utility/OutputUtilityTest.php
22-22: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\OutputUtility' in method 'testDebugWithVerboseOutput'. (Clean Code Rules)
(StaticAccess)
34-34: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\OutputUtility' in method 'testDebugWithVeryVerboseOutput'. (Clean Code Rules)
(StaticAccess)
44-44: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\OutputUtility' in method 'testDebugWithNonVerboseOutput'. (Clean Code Rules)
(StaticAccess)
55-55: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\OutputUtility' in method 'testDebugWithNonVeryVerboseOutputAndVeryVerboseFlag'. (Clean Code Rules)
(StaticAccess)
67-67: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\OutputUtility' in method 'testDebugWithNoNewLine'. (Clean Code Rules)
(StaticAccess)
tests/src/Validator/MismatchValidatorTest.php
32-32: Missing class import via use statement (line '32', column '27'). (Clean Code Rules)
(MissingImport)
82-82: Missing class import via use statement (line '82', column '27'). (Clean Code Rules)
(MissingImport)
120-120: Missing class import via use statement (line '120', column '27'). (Clean Code Rules)
(MissingImport)
131-131: Missing class import via use statement (line '131', column '23'). (Clean Code Rules)
(MissingImport)
tests/src/Utility/ClassUtilityTest.php
29-29: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\ClassUtility' in method 'testValidateClassWithNullClass'. (Clean Code Rules)
(StaticAccess)
39-39: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\ClassUtility' in method 'testValidateClassWithNonExistentClass'. (Clean Code Rules)
(StaticAccess)
49-49: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\ClassUtility' in method 'testValidateClassWithClassNotImplementingInterface'. (Clean Code Rules)
(StaticAccess)
57-57: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\ClassUtility' in method 'testValidateClassWithValidClass'. (Clean Code Rules)
(StaticAccess)
tests/src/Utility/PathUtilityTest.php
44-44: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\PathUtility' in method 'testNormalizeFolderPathWithTrailingSlash'. (Clean Code Rules)
(StaticAccess)
50-50: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\PathUtility' in method 'testNormalizeFolderPathWithoutTrailingSlash'. (Clean Code Rules)
(StaticAccess)
56-56: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\PathUtility' in method 'testNormalizeFolderPathWithDotSlashPrefix'. (Clean Code Rules)
(StaticAccess)
62-62: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\PathUtility' in method 'testNormalizeFolderPathWithEmptyPath'. (Clean Code Rules)
(StaticAccess)
68-68: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\PathUtility' in method 'testNormalizeFolderPathWhenPathIsCwd'. (Clean Code Rules)
(StaticAccess)
77-77: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\PathUtility' in method 'testNormalizeFolderPathWhenPathIsSubdirectoryOfCwd'. (Clean Code Rules)
(StaticAccess)
84-84: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Utility\PathUtility' in method 'testNormalizeFolderPathWhenPathIsNotRelatedToCwd'. (Clean Code Rules)
(StaticAccess)
tests/src/Parser/XliffParserTest.php
13-202: The class XliffParserTest has 14 public methods. Consider refactoring XliffParserTest to keep number of public methods under 10. (Code Size Rules)
(TooManyPublicMethods)
142-142: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\XliffParser' in method 'testGetSupportedFileExtensions'. (Clean Code Rules)
(StaticAccess)
148-148: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\XliffParser' in method 'testGetValidators'. (Clean Code Rules)
(StaticAccess)
🪛 GitHub Actions: CI
composer.json
[error] 1-1: Dependency 'armin/editorconfig-cli' requires PHP version ^8.2, but current PHP version is 8.1.32. This causes composer update to fail.
🔇 Additional comments (59)
.php-cs-fixer.php (1)
6-7: LGTM! Good practice to include test files in code style enforcement.The expansion to include the
testsdirectory while excludingtests/buildensures consistent code style across both source and test code, which aligns well with the comprehensive testing infrastructure being added.phpstan.neon (1)
5-5: Excellent addition for comprehensive static analysis.Including
tests/srcin the analysis paths ensures test code quality and catches potential issues early, which is essential for maintaining a robust test suite.tests/src/Fixtures/translations/xliff/success/locallang_be.xlf (1)
1-14: Well-structured XLIFF test fixture.The fixture correctly follows XLIFF 1.2 specification with proper XML declaration, namespace, and translation unit structure. This provides a solid foundation for testing successful translation parsing scenarios.
tests/src/Fixtures/translations/xliff/fail/locallang.xlf (1)
6-17: Intentionally invalid fixture for testing duplicate key detection.The fixture correctly implements duplicate trans-unit IDs (
key1andkey2each appear twice) to test failure scenarios. This provides an effective test case for validators that need to detect and handle duplicate translation keys.src/Utility/PathUtility.php (2)
11-20: Improved path resolution with good fallback handling.The use of
realpath()provides more robust path canonicalization and symbolic link resolution. The fallback logic for non-existent paths is well-designed, handling the common "./" prefix case appropriately.
23-31: Robust relative path calculation logic.The comparison logic using resolved canonical paths provides more accurate relative path determination compared to simple string-based approaches. The implementation correctly handles the conversion from absolute to relative paths.
rector.php (1)
20-20: LGTM! PHPUnit support added appropriately.The addition of
->withPHPUnit()aligns perfectly with the PR objective of adding comprehensive unit tests. This ensures Rector applies PHPUnit-specific refactoring rules during code analysis.src/FileDetector/Collector.php (1)
36-51: ```shell
#!/bin/bashLocate ParserInterface definition
echo "=== ParserInterface Definition ==="
rg -n "interface ParserInterface" -A 5 || trueecho -e "\n=== ParserRegistry Declaration ==="
rg -n "class ParserRegistry" -A 5 || trueecho -e "\n=== getAvailableParsers References ==="
rg -n "getAvailableParsers" -A 5 || trueecho -e "\n=== getSupportedFileExtensions Usage ==="
rg -n "getSupportedFileExtensions" -A 2 || true</details> <details> <summary>tests/src/Fixtures/translations/xliff/success/fr.locallang.xlf (1)</summary> `6-13`: **Clarify the intention behind empty source elements.** The XLIFF structure is valid, but the empty `<source/>` elements are unusual. In typical XLIFF files, source elements contain the original text to be translated. Is this intentional for testing specific validation scenarios, or should the source elements contain sample English text? For reference, a typical structure would be: ```xml <trans-unit id="key1"> <source>English text 1</source> <target>French1</target> </trans-unit>tests/src/Capability/ValidateTranslationCommandProviderTest.php (1)
13-20: LGTM! Well-structured unit test.The test correctly verifies that
ValidateTranslationCommandProvider::getCommands()returns exactly one command of the expected type. The assertions are appropriate and the test follows PHPUnit best practices.tests/src/Parser/ParserRegistryTest.php (1)
13-19: LGTM! Effective registry test.The test properly validates that
ParserRegistry::getAvailableParsers()returns the expected parser class and correct count. The static method access is necessary and appropriate for testing the registry functionality.tests/src/Fixtures/translations/xliff/success/de.locallang_be.xlf (1)
6-13: XLIFF structure is valid for test fixture.The file follows proper XLIFF 1.2 format with correct XML structure, namespace declaration, and translation units. The empty
<source/>elements appear to be intentional for this test scenario, likely testing cases where only target translations are present.tests/src/PluginTest.php (1)
14-21: LGTM! Comprehensive plugin capability test.The test effectively validates that the plugin correctly declares its command provider capability. Using both
assertArrayHasKeyandassertSameensures complete verification of the capability registration mechanism.tests/src/Fixtures/translations/xliff/success/locallang.xlf (1)
6-12: XLIFF structure is correct for source-only translation file.The file follows proper XLIFF 1.2 format with valid XML structure and contains appropriate source elements for English translations. This represents a valid source-only translation file scenario for testing purposes.
tests/src/Validator/ValidatorRegistryTest.php (1)
15-23: Test logic is correct and comprehensive.The test properly verifies that
ValidatorRegistry::getAvailableValidators()returns the expected set of validators and validates both content and count. This ensures the registry correctly exposes all available validator classes.src/Parser/XliffParser.php (1)
66-66: Improved type abstraction.The updated PHPDoc return type from
MismatchValidatortoValidatorInterfaceis more accurate since the method returns multiple validator classes that implement this interface. This change improves type safety and abstraction.tests/src/Fixtures/translations/xliff/fail/de.locallang.xlf (1)
1-16: Well-structured test fixture for failure scenarios.This XLIFF fixture appropriately represents a failure case with empty source elements but present German target translations. The structure is valid XLIFF 1.2 format and suitable for testing translation mismatch validation.
phpunit.xml (1)
1-30: Comprehensive and well-configured PHPUnit setup.The configuration properly sets up test discovery, coverage reporting with multiple formats (Clover, HTML, text), JUnit logging, and source code analysis. All settings follow PHPUnit best practices and support the comprehensive test suite being added.
tests/src/Fixtures/translations/xliff/fail/de.locallang_be.xlf (1)
1-20: Appropriate test fixture for duplicate key validation.This XLIFF fixture correctly demonstrates a failure case with duplicate translation unit IDs ("key2" on lines 10 and 14). The intentional duplication is perfect for testing the
DuplicatesValidatorfunctionality and ensuring proper error detection.tests/src/Fixtures/translations/xliff/fail/locallang_be.xlf (1)
1-14: LGTM! Well-structured XLIFF test fixture.The XLIFF structure is valid and appropriate for a failure test case. The absence of target elements in the translation units likely represents the intended failure scenario for validation testing.
src/Parser/ParserUtility.php (2)
17-18: Good refactoring to centralize parser management.The change to use
ParserRegistry::getAvailableParsers()improves code organization by centralizing parser management. The spread operator usage for array merging is also more readable than the previous approach.
52-52: Consistent improvement using centralized parser registry.This change aligns with the refactoring in
resolveAllowedFileExtensions()and maintains consistency by using the centralizedParserRegistryfor parser management.tests/src/FileDetector/PrefixFileDetectorTest.php (1)
10-85: Excellent test coverage for PrefixFileDetector functionality.The test class provides comprehensive coverage of the
mapTranslationSetmethod:
- ✅ Files with language prefixes
- ✅ Mixed prefixed and non-prefixed files
- ✅ Files without prefixes
- ✅ Empty input handling
The test implementation follows good practices with clear AAA structure, appropriate assertions, and descriptive test names.
.github/workflows/ci.yml (1)
1-61: Well-designed CI workflow with comprehensive matrix testing.The CI configuration provides excellent coverage:
- ✅ Multiple PHP versions (8.1, 8.3, 8.4)
- ✅ Multiple Symfony versions (5.x, 6.x, 7.x)
- ✅ Both lowest and stable dependency resolution
- ✅ Required extensions for XLIFF parsing
- ✅ Proper use of SYMFONY_REQUIRE for version constraints
The matrix strategy effectively tests compatibility across supported PHP and Symfony versions while maintaining reasonable CI execution time.
tests/src/FileDetector/CollectorTest.php (1)
13-107: Outstanding test implementation with comprehensive coverage.This test class demonstrates excellent testing practices:
- ✅ Proper test isolation with temp directory setup/teardown
- ✅ Comprehensive scenario coverage (valid path, invalid path, exclusions, no matches)
- ✅ Appropriate mocking of dependencies (Logger, Detector)
- ✅ Verification of both outputs and side effects (logging behavior)
- ✅ Clean file system operations with proper cleanup
The test methods cover all critical paths and edge cases for the Collector functionality.
tests/src/Validator/DuplicatesValidatorTest.php (5)
15-28: Excellent test coverage for duplicate detection logic.The test correctly validates that
processFilereturns the expected duplicate count structure['key1' => 2, 'key2' => 2]when duplicates are present. The mock setup properly simulates the parser behavior and the logger expectation ensures no errors are logged for valid processing.
30-43: Good coverage for the non-duplicate scenario.The test appropriately verifies that an empty result is returned when no duplicates exist, and confirms no error logging occurs during successful processing.
45-60: Proper error handling test for invalid files.The test correctly validates error logging behavior when the parser returns
nullfor invalid files. The string matching assertion withstringContainsis appropriate for verifying the error message content.
62-97: Comprehensive output rendering test with accurate table formatting.The test validates the console table output format correctly, including proper handling of multiple files and the expected table structure. The use of
BufferedOutputand trimming for comparison is a solid approach.
99-105: Simple but effective test for the explain method.The assertion correctly verifies that the explanation contains the expected "duplicate keys" text, ensuring the method returns meaningful information.
tests/src/Utility/OutputUtilityTest.php (5)
13-23: Correct test for basic verbose output.The test properly validates that when output is verbose (but not very verbose), the
writelnmethod is called once with the unmodified message. The mock expectations correctly reflect the expected behavior.
25-35: Accurate test for very verbose output with color formatting.The test correctly verifies that very verbose messages receive gray color formatting (
<fg=gray>Very verbose message</>) and are written usingwriteln. The mock setup properly simulates both verbose and very verbose conditions.
37-45: Proper test for non-verbose output early return.The test accurately validates that when output is not verbose, no write operations occur. This correctly tests the early return behavior in the
OutputUtility::debugmethod.
47-56: Correct test for very verbose flag with non-very-verbose output.The test properly validates the second early return condition where the
veryVerboseflag is set but the output is not very verbose, ensuring no output is written in this scenario.
58-68: Good test for write method usage without newline.The test correctly verifies that when
newLineis false, thewritemethod is used instead ofwriteln. The parameter ordering in the method call(output, message, veryVerbose=false, newLine=false)is correctly tested.composer.json (3)
30-33: Good dependency additions for enhanced testing and static analysis.The addition of PHPUnit and PHPStan extensions improves the testing and static analysis capabilities. The version constraints are appropriate for the project's PHP requirements.
41-45: Correct autoload-dev configuration for test namespace.The PSR-4 autoload configuration properly maps the test namespace
MoveElevator\ComposerTranslationValidator\Tests\to thetests/src/directory, enabling proper autoloading of test classes.
79-81: Well-structured test scripts with appropriate configurations.The test scripts are properly defined with coverage support and memory limit configuration for PHPStan. The separation of coverage and non-coverage test runs provides flexibility.
tests/src/Parser/ParserUtilityTest.php (4)
13-20: Good test coverage for file extension resolution.The test correctly verifies that the allowed file extensions include both 'xliff' and 'xlf', and validates that exactly 2 unique extensions are returned. The use of
array_unique()in the assertion is a good practice to ensure no duplicates exist.
22-28: Appropriate test for parser class resolution.The test properly validates that
XliffParser::classis included in the resolved parser classes and that exactly one parser class is returned, which aligns with the current parser implementation.
30-41: Comprehensive test for supported file extension mapping.The test correctly validates that both
.xlfand.xlifffile extensions map to theXliffParserclass. Testing both extensions ensures complete coverage of supported formats.
43-49: Proper negative test case for unsupported extensions.The test appropriately validates that unsupported file extensions (like
.txt) returnnull, ensuring the utility correctly handles invalid file types.tests/src/Command/ValidateTranslationCommandTest.php (6)
16-32: Excellent test for successful command execution.The test properly validates the happy path scenario with valid translation files, using the
--dry-runflag appropriately and asserting both the success message and exit code 0. The fixture path reference is correctly constructed.
34-48: Good test for missing path arguments.The test correctly validates the error handling when no paths are provided, properly asserting the error message and exit code 1. The empty array for the
pathargument effectively simulates the missing paths scenario.
50-64: Appropriate test for empty directory handling.The test validates the scenario where specified directories contain no translation files, correctly expecting an informational message and exit code 0 (not an error condition).
66-81: Proper test for invalid validator class handling.The test correctly validates error handling for invalid validator classes, using a non-existent class name and asserting both the implementation error message and exit code 1.
83-97: Good test for validation failure scenarios.The test properly validates command behavior when translation files contain validation errors, using the fail fixture directory and asserting both the failure message and exit code 1.
99-114: Excellent test for dry-run mode with errors.The test correctly validates that dry-run mode reports validation failures but doesn't cause the command to exit with a failure code (exit code 0), which is the expected behavior for dry-run scenarios.
tests/src/Validator/MismatchValidatorTest.php (4)
46-61: LGTM - Good error handling test.The test properly verifies both the return value and logging behavior when processing invalid files.
63-99: LGTM - Comprehensive mismatch detection test.The test effectively validates the core functionality of detecting translation key mismatches between files.
101-126: LGTM - Important negative test case.This test ensures the validator correctly identifies when no mismatches exist, preventing false positives.
162-168: LGTM - Simple but effective validation.The test appropriately verifies that the explain method returns descriptive content.
tests/src/Validator/SchemaValidatorTest.php (3)
20-74: LGTM - Excellent test setup and cleanup pattern.The setup creates realistic test data with proper isolation, and the teardown ensures complete cleanup. The recursive directory removal is implemented correctly.
76-118: LGTM - Comprehensive validation test coverage.The tests effectively cover valid files, invalid schema violations, and error handling for missing files. The mock expectations properly verify logging behavior.
120-161: LGTM - Well-structured output rendering test.The test validates table formatting with realistic XML validation error data. The use of
assertSamefor exact output matching is appropriate here.tests/src/Utility/ClassUtilityTest.php (2)
11-21: LGTM - Clean test fixture design.The dummy interface and classes provide good isolation for testing class validation logic without external dependencies.
24-58: LGTM - Comprehensive class validation test suite.The tests thoroughly cover all validation scenarios with proper mock expectations. The static method access warnings from PHPMD are appropriate here since you're testing a static utility method.
tests/src/Utility/PathUtilityTest.php (1)
15-85: LGTM - Comprehensive path normalization test coverage.The test suite effectively covers all scenarios for path normalization, including edge cases like empty paths and working directory relationships. The temporary directory setup and cleanup is well-implemented.
tests/src/Parser/XliffParserTest.php (1)
112-201: LGTM - Comprehensive parser functionality coverage.The tests thoroughly validate all aspects of XLIFF parsing, including edge cases like empty targets and missing language information. The language detection logic is well-tested across multiple scenarios.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
.github/workflows/ci.yml (2)
51-53:--no-suggestflag is obsolete in Composer 2Composer 2 dropped the “suggest” output entirely; the flag is ignored and may be removed in a future version.
Consider replacing with--no-scripts --no-ansifor quieter, deterministic installs.
40-60: Cache Composer dependencies to cut CI timeA cache step keyed on
composer.locktypically divides install time by ~5×.Example (insert before “Install Composer dependencies”):
- name: Cache Composer uses: actions/cache@v4 with: path: ~/.composer/cache/files key: ${{ runner.os }}-php-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }}Optional but recommended for larger matrices.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/ci.yml(1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/ci.yml
17-17: unexpected key "exclude" for "strategy" section. expected one of "fail-fast", "matrix", "max-parallel"
(syntax-check)
# Conflicts: # composer.lock # src/FileDetector/Collector.php # src/Parser/XliffParser.php
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
.github/workflows/ci.yml (4)
10-11: Consider disabling matrix fail-fast to surface all failing combosBy default a single failure aborts the remaining matrix jobs.
Addingfail-fast: falsehelps you see the full compatibility picture in one run.strategy: + fail-fast: false matrix:
74-80: Composer step lacks caching – CI time will scale linearly with the matrixEach job reinstalls the full dependency tree.
Leveraging the built-in Composer cache ofshivammathur/setup-php(or an
explicitactions/cachestep keyed oncomposer.lock+ PHP version) will cut
minutes off the workflow and lower network flakiness.Reference snippet (if you prefer an explicit cache):
- name: Cache Composer uses: actions/cache@v4 with: path: ~/.composer/cache/files key: composer-${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }}
74-75:--no-suggestis obsolete in recent Composer versionsComposer ≥ 2.3 no longer prints the “suggest” section, and the flag was removed.
While it is ignored today, older versions (≤ 2.2) accept it, but future versions
may throw. Safe to drop:-run: composer update --no-interaction --no-progress --no-suggest +run: composer update --no-interaction --no-progress
113-113: Add a trailing newlineCI linters (e.g. yamllint) are already flagging the missing EOL.
Insert a blank line afterretention-days: 5.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (2)
.github/workflows/ci.yml(1 hunks)composer.json(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- composer.json
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/ci.yml
[error] 113-113: no new line character at the end of file
(new-line-at-end-of-file)
🔇 Additional comments (1)
.github/workflows/ci.yml (1)
96-98: Verify availability of PHP 8.4 & Composer 2.8 on the runner
setup-phpinstalls nightly builds, but GitHub occasionally removes them or
changes labels. Confirm that these versions resolve; otherwise pin to
8.4snapshot/ the latest published Composer release to avoid silent job
failures.
If needed:php-version: '8.4snapshot' tools: composer:latest
…mlParser, and AbstractValidator
…ging in AbstractValidator
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
tests/src/Parser/ParserRegistryTest.php (1)
14-21: Consider making the test more resilient to parser additions.The test logic is correct, but the hardcoded count assertion
$this->assertCount(2, $parsers)could break if parsers are added or removed in the future.Consider using a minimum count assertion instead:
- $this->assertCount(2, $parsers); + $this->assertGreaterThanOrEqual(2, $parsers, 'Expected at least XliffParser and YamlParser');Alternatively, if the exact count is intentional for validation purposes, the current approach is acceptable.
src/Parser/ParserRegistry.php (1)
20-36: Add missing documentation for the new method.The method logic is correct and provides a clean way to resolve parser classes based on file extensions. However, the documentation is incomplete as flagged by static analysis.
/** + * Resolves the appropriate parser class for a given file path based on its extension. + * + * @param string $filePath The path to the file to resolve a parser for * @return class-string<ParserInterface>|null */
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (21)
.gitignore(1 hunks)README.md(1 hunks)composer.json(2 hunks)phpstan.neon(1 hunks)rector.php(1 hunks)src/Command/ValidateTranslationCommand.php(0 hunks)src/FileDetector/Collector.php(1 hunks)src/FileDetector/SuffixFileDetector.php(1 hunks)src/Parser/ParserRegistry.php(1 hunks)src/Parser/ParserUtility.php(0 hunks)src/Validator/AbstractValidator.php(2 hunks)src/Validator/ValidatorInterface.php(1 hunks)tests/Build/app/composer.json(0 hunks)tests/composer.json(1 hunks)tests/src/FileDetector/CollectorTest.php(1 hunks)tests/src/FileDetector/FileDetectorRegistryTest.php(1 hunks)tests/src/FileDetector/SuffixFileDetectorTest.php(1 hunks)tests/src/Parser/ParserRegistryTest.php(1 hunks)tests/src/Parser/XliffParserTest.php(1 hunks)tests/src/Parser/YamlParserTest.php(1 hunks)tests/src/Validator/AbstractValidatorTest.php(1 hunks)
💤 Files with no reviewable changes (3)
- tests/Build/app/composer.json
- src/Command/ValidateTranslationCommand.php
- src/Parser/ParserUtility.php
✅ Files skipped from review due to trivial changes (3)
- README.md
- .gitignore
- tests/composer.json
🚧 Files skipped from review as they are similar to previous changes (3)
- rector.php
- phpstan.neon
- composer.json
🧰 Additional context used
🧬 Code Graph Analysis (6)
tests/src/FileDetector/FileDetectorRegistryTest.php (3)
src/FileDetector/FileDetectorRegistry.php (2)
FileDetectorRegistry(7-19)getAvailableFileDetectors(12-18)src/FileDetector/PrefixFileDetector.php (1)
PrefixFileDetector(7-31)src/FileDetector/SuffixFileDetector.php (1)
SuffixFileDetector(7-28)
src/Parser/ParserRegistry.php (4)
src/Parser/XliffParser.php (1)
getSupportedFileExtensions(55-58)src/Parser/YamlParser.php (1)
getSupportedFileExtensions(69-72)src/Parser/AbstractParser.php (1)
getSupportedFileExtensions(46-46)src/Parser/ParserInterface.php (1)
getSupportedFileExtensions(14-14)
src/Validator/ValidatorInterface.php (1)
src/Validator/AbstractValidator.php (1)
validate(28-65)
tests/src/FileDetector/SuffixFileDetectorTest.php (1)
src/FileDetector/SuffixFileDetector.php (1)
SuffixFileDetector(7-28)
src/FileDetector/Collector.php (4)
src/Parser/ParserInterface.php (1)
getSupportedFileExtensions(14-14)src/FileDetector/SuffixFileDetector.php (1)
mapTranslationSet(14-27)src/FileDetector/PrefixFileDetector.php (1)
mapTranslationSet(14-30)src/FileDetector/FileDetectorRegistry.php (2)
FileDetectorRegistry(7-19)getAvailableFileDetectors(12-18)
tests/src/Parser/XliffParserTest.php (4)
src/Parser/XliffParser.php (5)
XliffParser(7-70)extractKeys(31-39)getContentByKey(41-50)getSupportedFileExtensions(55-58)getLanguage(60-69)tests/src/FileDetector/CollectorTest.php (3)
setUp(17-22)tearDown(24-30)removeDirectory(32-39)tests/src/Utility/PathUtilityTest.php (3)
setUp(15-21)tearDown(23-30)removeDirectory(32-39)tests/src/Validator/SchemaValidatorTest.php (3)
setUp(20-57)tearDown(59-65)removeDirectory(67-74)
🪛 PHPMD (2.15.0)
src/Validator/AbstractValidator.php
40-40: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\ParserRegistry' in method 'validate'. (Clean Code Rules)
(StaticAccess)
tests/src/FileDetector/FileDetectorRegistryTest.php
16-16: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\FileDetector\FileDetectorRegistry' in method 'testGetAvailableFileDetectors'. (Clean Code Rules)
(StaticAccess)
tests/src/Parser/ParserRegistryTest.php
16-16: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\ParserRegistry' in method 'testGetAvailableParsers'. (Clean Code Rules)
(StaticAccess)
tests/src/Parser/YamlParserTest.php
129-129: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\YamlParser' in method 'testGetSupportedFileExtensions'. (Clean Code Rules)
(StaticAccess)
tests/src/Validator/AbstractValidatorTest.php
124-124: Missing class import via use statement (line '124', column '27'). (Clean Code Rules)
(MissingImport)
src/FileDetector/Collector.php
52-52: Avoid using static access to class 'MoveElevator\ComposerTranslationValidator\FileDetector\FileDetectorRegistry' in method 'collectFiles'. (Clean Code Rules)
(StaticAccess)
tests/src/Parser/XliffParserTest.php
10-193: The class XliffParserTest has 13 public methods. Consider refactoring XliffParserTest to keep number of public methods under 10. (Code Size Rules)
(TooManyPublicMethods)
139-139: Avoid using static access to class '\MoveElevator\ComposerTranslationValidator\Parser\XliffParser' in method 'testGetSupportedFileExtensions'. (Clean Code Rules)
(StaticAccess)
🪛 phpcs (3.7.2)
tests/src/FileDetector/FileDetectorRegistryTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 12-12: Missing doc comment for class FileDetectorRegistryTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 14-14: Missing doc comment for function testGetAvailableFileDetectors()
(PEAR.Commenting.FunctionComment.Missing)
src/Parser/ParserRegistry.php
[ERROR] 20-20: Missing short description in doc comment
(Generic.Commenting.DocComment.MissingShort)
[ERROR] 20-20: Doc comment for parameter "$filePath" missing
(PEAR.Commenting.FunctionComment.MissingParamTag)
tests/src/Parser/ParserRegistryTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 12-12: Missing doc comment for class ParserRegistryTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 14-14: Missing doc comment for function testGetAvailableParsers()
(PEAR.Commenting.FunctionComment.Missing)
src/Validator/ValidatorInterface.php
[ERROR] 25-25: Missing short description in doc comment
(Generic.Commenting.DocComment.MissingShort)
[ERROR] 26-26: Missing parameter comment
(PEAR.Commenting.FunctionComment.MissingParamComment)
[ERROR] 27-27: Missing parameter comment
(PEAR.Commenting.FunctionComment.MissingParamComment)
tests/src/FileDetector/SuffixFileDetectorTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 10-10: Missing doc comment for class SuffixFileDetectorTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 12-12: Missing doc comment for function testMapTranslationSetWithSuffixFiles()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 31-31: Missing doc comment for function testMapTranslationSetWithMixedFiles()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 53-53: Missing doc comment for function testMapTranslationSetWithNoSuffixFiles()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 66-66: Missing doc comment for function testMapTranslationSetWithEmptyArray()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Parser/YamlParserTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 10-10: Missing doc comment for class YamlParserTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 12-12: Private member variable "tempDir" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 13-13: Private member variable "validYamlFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 14-14: Private member variable "invalidYamlFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 15-15: Private member variable "nestedYamlFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 16-16: Private member variable "languageYamlFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 18-18: Missing doc comment for function setUp()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 25-25: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 32-32: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 39-39: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 47-47: Opening parenthesis of a multi-line function call must be the last content on the line
(PEAR.Functions.FunctionCallSignature.ContentAfterOpenBracket)
[ERROR] 53-53: Missing doc comment for function tearDown()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 61-61: Missing doc comment for function removeDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 61-61: Private method name "YamlParserTest::removeDirectory" must be prefixed with an underscore
(PEAR.NamingConventions.ValidFunctionName.PrivateNoUnderscore)
[ERROR] 70-70: Missing doc comment for function testConstructorThrowsExceptionIfFileDoesNotExist()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 77-77: Missing doc comment for function testConstructorThrowsExceptionIfFileIsNotReadable()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 88-88: Missing doc comment for function testConstructorThrowsExceptionIfFileHasInvalidExtension()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 98-98: Missing doc comment for function testConstructorThrowsExceptionIfYamlIsInvalid()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 105-105: Missing doc comment for function testExtractKeys()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 116-116: Missing doc comment for function testGetContentByKey()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 127-127: Missing doc comment for function testGetSupportedFileExtensions()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 133-133: Missing doc comment for function testGetLanguage()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Validator/AbstractValidatorTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 15-15: You must use "/**" style comments for a class comment
(PEAR.Commenting.ClassComment.WrongStyle)
[ERROR] 17-17: Missing short description in doc comment
(Generic.Commenting.DocComment.MissingShort)
[ERROR] 17-17: Doc comment for parameter "$file" missing
(PEAR.Commenting.FunctionComment.MissingParamTag)
[ERROR] 30-30: Missing short description in doc comment
(Generic.Commenting.DocComment.MissingShort)
[ERROR] 38-38: Missing doc comment for function explain()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 43-43: Missing short description in doc comment
(Generic.Commenting.DocComment.MissingShort)
[ERROR] 44-44: Missing parameter comment
(PEAR.Commenting.FunctionComment.MissingParamComment)
[ERROR] 45-45: Missing parameter comment
(PEAR.Commenting.FunctionComment.MissingParamComment)
[ERROR] 54-54: Missing short description in doc comment
(Generic.Commenting.DocComment.MissingShort)
[ERROR] 62-62: Missing doc comment for function renderIssueSets()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 69-69: You must use "/**" style comments for a class comment
(PEAR.Commenting.ClassComment.WrongStyle)
[ERROR] 71-71: Missing doc comment for function __construct()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 75-75: Missing doc comment for function extractKeys()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 80-80: Missing doc comment for function getContentByKey()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 85-85: Missing doc comment for function getSupportedFileExtensions()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 90-90: Missing doc comment for function getFileName()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 95-95: Missing doc comment for function getFileDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 100-100: Missing doc comment for function getFilePath()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 105-105: Missing doc comment for function getLanguage()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 111-111: Missing doc comment for class AbstractValidatorTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 113-113: Private member variable "loggerMock" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 115-115: Missing doc comment for function setUp()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 121-121: Missing doc comment for function testConstructorSetsLogger()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 130-130: Missing doc comment for function testPostProcessIsCalled()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/FileDetector/CollectorTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 13-13: Missing doc comment for class CollectorTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 15-15: Private member variable "tempDir" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 17-17: Missing doc comment for function setUp()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 24-24: Missing doc comment for function tearDown()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 32-32: Missing doc comment for function removeDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 32-32: Private method name "CollectorTest::removeDirectory" must be prefixed with an underscore
(PEAR.NamingConventions.ValidFunctionName.PrivateNoUnderscore)
[ERROR] 41-41: Missing doc comment for function testCollectFilesWithValidPath()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 58-58: Missing doc comment for function testCollectFilesWithInvalidPath()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 73-73: Missing doc comment for function testCollectFilesWithExcludedFiles()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 91-91: Missing doc comment for function testCollectFilesWithNoMatchingFiles()
(PEAR.Commenting.FunctionComment.Missing)
tests/src/Parser/XliffParserTest.php
[ERROR] 2-2: Missing file doc comment
(PEAR.Commenting.FileComment.Missing)
[ERROR] 10-10: Missing doc comment for class XliffParserTest
(PEAR.Commenting.ClassComment.Missing)
[ERROR] 12-12: Private member variable "tempDir" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 13-13: Private member variable "validXliffFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 14-14: Private member variable "validXliffContent" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 36-36: Private member variable "prefixedXliffFile" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 37-37: Private member variable "prefixedXliffContent" must be prefixed with an underscore
(PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore)
[ERROR] 51-51: Missing doc comment for function setUp()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 64-64: Missing doc comment for function tearDown()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 72-72: Missing doc comment for function removeDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 72-72: Private method name "XliffParserTest::removeDirectory" must be prefixed with an underscore
(PEAR.NamingConventions.ValidFunctionName.PrivateNoUnderscore)
[ERROR] 81-81: Missing doc comment for function testConstructorThrowsExceptionIfFileDoesNotExist()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 88-88: Missing doc comment for function testConstructorThrowsExceptionIfFileIsNotReadable()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 99-99: Missing doc comment for function testConstructorThrowsExceptionIfFileHasInvalidExtension()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 109-109: Missing doc comment for function testExtractKeys()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 117-117: Missing doc comment for function testGetContentByKeySource()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 127-127: Missing doc comment for function testGetContentByKeyTarget()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 137-137: Missing doc comment for function testGetSupportedFileExtensions()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 143-143: Missing doc comment for function testGetFileName()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 149-149: Missing doc comment for function testGetFileDirectory()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 155-155: Missing doc comment for function testGetFilePath()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 161-161: Missing doc comment for function testGetLanguageFromPrefixedFileName()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 167-167: Missing doc comment for function testGetLanguageFromSourceLanguageAttribute()
(PEAR.Commenting.FunctionComment.Missing)
[ERROR] 173-173: Missing doc comment for function testGetLanguageWhenNoPrefixAndNoSourceLanguage()
(PEAR.Commenting.FunctionComment.Missing)
🔇 Additional comments (23)
src/FileDetector/SuffixFileDetector.php (1)
20-20: LGTM: Regex pattern correctly identifies files with language suffixes.The simplified regex pattern effectively matches translation files with language codes (e.g.,
file.en.xlf,config.de_DE.yml) while excluding files without proper suffix patterns. This aligns with the intended behavior of only grouping files with language suffixes.src/FileDetector/Collector.php (1)
35-38: LGTM: Method existence check correctly removed.Since
getSupportedFileExtensions()is required byParserInterface, the method existence check was redundant. All parser classes implementing the interface must provide this method.src/Validator/AbstractValidator.php (3)
8-8: LGTM: Correct import change for refactored parser resolution.The import change from
ParserUtilitytoParserRegistryaligns with the architectural refactoring to centralize parser management in the registry.
30-31: LGTM: Improved readability in class name extraction.Extracting the class name into a variable before using it in the log message improves code readability and maintainability.
Also applies to: 35-35
40-40: LGTM: Parser resolution updated to use ParserRegistry.The change from
ParserUtility::resolveParserClasstoParserRegistry::resolveParserClasscorrectly implements the architectural refactoring to centralize parser management.tests/src/FileDetector/FileDetectorRegistryTest.php (1)
14-21: Well-structured test with comprehensive assertions.The test effectively validates the registry behavior by checking both the presence of expected detectors and the total count. This ensures the registry maintains consistency.
tests/src/FileDetector/CollectorTest.php (3)
17-30: Excellent test setup with proper resource management.The setUp/tearDown pattern with unique temporary directories ensures test isolation and proper cleanup.
32-39: Robust recursive directory cleanup implementation.The recursive directory removal logic properly handles both files and subdirectories, ensuring complete cleanup of test resources.
41-106: Comprehensive test coverage with appropriate mocking.The test methods cover all critical scenarios:
- Valid path processing with expected output structure
- Error handling for invalid paths with logging verification
- Exclusion filtering functionality
- Edge case handling for directories with no matching files
The use of mocks for Logger and DetectorInterface is appropriate and allows precise verification of interactions.
tests/src/FileDetector/SuffixFileDetectorTest.php (1)
12-74: Thorough test coverage validating suffix detection logic.The test cases comprehensively validate the SuffixFileDetector behavior:
- Files with language suffixes are correctly grouped by base name
- Files without language suffixes are properly excluded
- Mixed scenarios work as expected
- Edge cases (empty input) are handled correctly
The test expectations align perfectly with the regex pattern used in the SuffixFileDetector implementation.
tests/src/Validator/AbstractValidatorTest.php (2)
15-66: Well-designed test doubles for AbstractValidator testing.The ConcreteValidator and TestParser classes provide appropriate minimal implementations for testing the abstract validator framework. The dummy implementations focus on the essential behavior needed for testing.
130-147: Effective verification of validator lifecycle.The test properly verifies that the postProcess method is called during validation using PHPUnit mocks. This ensures the abstract validator's template method pattern works correctly.
tests/src/Parser/XliffParserTest.php (6)
51-79: Test setup and cleanup implementation looks solid.The temporary directory setup and recursive cleanup follows established patterns from other test files. The
removeDirectorymethod correctly handles nested directory removal.
109-115: Excellent key extraction test coverage.The test properly validates that all trans-unit IDs are extracted correctly from the XLIFF structure.
127-135: Good test for empty target handling.The test correctly verifies that empty target elements return
nullrather than empty strings, which aligns with the parser's implementation that checks for non-empty content.
161-171: Comprehensive language detection testing.The tests cover both language detection strategies: filename prefix parsing and XML source-language attribute fallback. This thoroughly validates the
getLanguage()method's dual approach.
173-192: Edge case handling for missing language information.This test properly validates the fallback behavior when neither filename prefix nor XML attribute provides language information, ensuring the method returns an empty string rather than throwing an exception.
88-97: Potential cross-platform compatibility issue with file permissions.Using
chmod($unreadableFile, 0000)may not work consistently across all operating systems, particularly Windows. Consider adding a platform check or using PHPUnit's@requiresannotation to skip this test on incompatible systems.#!/bin/bash # Check if other test files in the codebase use similar permission-based tests rg -A 5 -B 5 "chmod.*0000|chmod.*0o000" tests/tests/src/Parser/YamlParserTest.php (5)
18-51: Well-designed test data setup covering multiple YAML scenarios.The test fixtures appropriately cover:
- Valid flat YAML structure
- Invalid YAML with improper indentation (line 32-36)
- Nested YAML structure for dot notation testing
- Language-specific filename pattern
The invalid YAML correctly demonstrates malformed syntax with inconsistent indentation.
77-86: Cross-platform file permission test concern.Same issue as in XliffParserTest -
chmod($unreadableFile, 0000)may not work consistently on Windows systems.Consider adding a platform check or skipping this test on Windows:
public function testConstructorThrowsExceptionIfFileIsNotReadable(): void { + if (DIRECTORY_SEPARATOR === '\\') { + $this->markTestSkipped('File permission tests not reliable on Windows'); + } $unreadableFile = $this->tempDir.'/unreadable.yaml'; file_put_contents($unreadableFile, 'content'); chmod($unreadableFile, 0000); // Make unreadable
105-114: Excellent nested key extraction testing.The test properly validates that nested YAML structures are flattened using dot notation (
parent.child1,parent.child2), which is crucial for YAML parser functionality.
116-125: Comprehensive content retrieval testing.Tests cover both flat and nested key retrieval, including proper
nullhandling for non-existent keys. The nested key test withparent.child1validates the dot notation access correctly.
133-140: Language detection logic properly tested.The test validates language extraction from filename patterns (e.g.,
messages.de.yaml→'de') and fallback to empty string when no language pattern is found.
| /** | ||
| * @param array<string> $files | ||
| * @param class-string<ParserInterface> $parserClass | ||
| * | ||
| * @return array<string, mixed> | ||
| */ | ||
| public function validate(array $files, string $parserClass): array; |
There was a problem hiding this comment.
Fix type mismatch and add proper documentation.
The interface declares $parserClass as string, but the implementation in AbstractValidator uses ?string (nullable). This type mismatch will cause compatibility issues.
Apply this diff to fix the type mismatch and add proper documentation:
+ /**
+ * Validates translation files using the specified parser class.
+ *
+ * @param array<string> $files Array of file paths to validate
+ * @param class-string<ParserInterface>|null $parserClass Parser class to use, or null to auto-resolve
+ *
+ * @return array<string, mixed> Validation results keyed by filename
+ */
- public function validate(array $files, string $parserClass): array;
+ public function validate(array $files, ?string $parserClass): array;Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 phpcs (3.7.2)
[ERROR] 25-25: Missing short description in doc comment
(Generic.Commenting.DocComment.MissingShort)
[ERROR] 26-26: Missing parameter comment
(PEAR.Commenting.FunctionComment.MissingParamComment)
[ERROR] 27-27: Missing parameter comment
(PEAR.Commenting.FunctionComment.MissingParamComment)
🤖 Prompt for AI Agents
In src/Validator/ValidatorInterface.php around lines 25 to 31, the method
validate declares the parameter $parserClass as a non-nullable string, but the
implementation uses a nullable string (?string), causing a type mismatch. Update
the interface method signature to accept ?string for $parserClass to match the
implementation and modify the PHPDoc to reflect that $parserClass can be null by
changing the type to class-string<ParserInterface>|null.
| public function testConstructorSetsLogger(): void | ||
| { | ||
| $validator = new ConcreteValidator($this->loggerMock); | ||
| $reflection = new \ReflectionClass($validator); | ||
| $loggerProperty = $reflection->getProperty('logger'); | ||
| $loggerProperty->setAccessible(true); | ||
| $this->assertSame($this->loggerMock, $loggerProperty->getValue($validator)); | ||
| } |
There was a problem hiding this comment.
Add missing import for ReflectionClass.
The test uses reflection to verify internal state but is missing the import statement.
+use ReflectionClass;
// Later in the test method:
- $reflection = new \ReflectionClass($validator);
+ $reflection = new ReflectionClass($validator);🧰 Tools
🪛 phpcs (3.7.2)
[ERROR] 121-121: Missing doc comment for function testConstructorSetsLogger()
(PEAR.Commenting.FunctionComment.Missing)
🪛 PHPMD (2.15.0)
124-124: Missing class import via use statement (line '124', column '27'). (Clean Code Rules)
(MissingImport)
🤖 Prompt for AI Agents
In tests/src/Validator/AbstractValidatorTest.php around lines 121 to 128, the
test uses ReflectionClass but lacks the necessary import. Add a use statement
for ReflectionClass at the top of the file to properly import it and avoid class
not found errors.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
.github/workflows/tests.yml (2)
67-74: Add Composer cache step – 3-5× faster jobs, lower CI minutesEach matrix job does a full
composer update; without caching this redownloads 100 + MB every run. Insert anactions/cache@v3step before dependency installation:- - name: Install Composer dependencies - run: composer update --no-interaction --no-progress --no-suggest + - name: Cache Composer + uses: actions/cache@v3 + with: + path: ~/.composer/cache/files + key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ matrix.composer_version }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ matrix.composer_version }}- + + - name: Install Composer dependencies + run: composer update --no-interaction --no-progressThis drops
--no-suggest(deprecated in Composer ≥2.3).
Expect ~60 % runtime reduction on cache hits.
74-80: Prefercomposer installfor deterministic builds
composer updaterespectsSYMFONY_REQUIREbut ignorescomposer.lock, so every run may drift and break reproducibility. A common pattern is:
- Run
composer require symfony/*:$SYMFONY_REQUIRE --no-update- Then
composer install --no-interaction --no-progressThis locks the exact resolved versions and still honours the matrix constraint, yielding deterministic, cache-friendly builds.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/tests.yml(1 hunks)
🔇 Additional comments (1)
.github/workflows/tests.yml (1)
14-60: Verify readiness for PHP 8.4 & Composer matrix explosionThe matrix includes PHP 8.4 (lines 50-59). As of today, PHP 8.4 is unreleased and nightly builds can be unstable; Composer 2.4 may also be EOL soon.
Please double-check that:
shivammathur/setup-php@v2supports nightly 8.4 tags.- Your codebase is actively tested against 8.4 locally (fatal deprecations may break the whole matrix).
If 8.4 images are unavailable the job will silently fail. You can guard with:
strategy: fail-fast: false matrix: include: # … - php: '8.4' experimental: true # …and then skip on missing images:
- name: Skip if experimental PHP version not available if: matrix.experimental == true && steps.setup-php.outcome == 'failure' run: echo "PHP ${{ matrix.php }} not available – skipping"
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/tests.yml(1 hunks)
🔇 Additional comments (1)
.github/workflows/tests.yml (1)
2-8: Trigger section now covers bothpushandpull_request– good catchIncluding
pull_requestresolves the gap flagged in the earlier review and guarantees CI feedback for contributors working from forks.
| - name: Install Composer dependencies | ||
| run: composer update --no-interaction --no-progress --no-suggest | ||
| env: | ||
| SYMFONY_REQUIRE: ${{ matrix.symfony_constraint }} |
There was a problem hiding this comment.
--no-suggest causes fatal errors with Composer ≥ 2.4
The --no-suggest flag was removed in Composer 2.4, yet this workflow pulls Composer 2.4 & 2.8 in multiple matrix combinations. All affected jobs will exit with
Error: Unknown option "--no-suggest".
Replace the flag with nothing (or --quiet if you need silence). Same change is required in both tests and coverage jobs.
-run: composer update --no-interaction --no-progress --no-suggest
+run: composer update --no-interaction --no-progressAlso applies to: 101-104
🤖 Prompt for AI Agents
In .github/workflows/tests.yml around lines 77 to 80 and also lines 101 to 104,
the use of the --no-suggest flag with the composer update command causes fatal
errors in Composer versions 2.4 and above because this flag was removed. To fix
this, remove the --no-suggest flag entirely from the composer update commands in
both the tests and coverage jobs, optionally replacing it with --quiet if you
want to suppress output.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
README.md (3)
13-13: Fix plural-singular mismatch in descriptionMinor grammar tweak to make the sentence read naturally.
-Provides a command `validate-translations` to check for translations mismatches, duplicates and schema validation. +Provides a command `validate-translations` to check for translation mismatches, duplicates, and schema validation.
53-54: Standardise YAML row wording & capitalisationConsistent casing and removing the redundant “language” improves readability.
-| XLIFF | `*.xlf`, `*.xliff` | Supports source/target translations in xliff language files. Used e.g. within [TYPO3 CMS](https://typo3.org/). | `locallang.xlf`, `de.locallang.xlf` | -| Yaml | `*.yml`, `*.yaml` | Supports yaml language files. Used e.g. within [Symfony Framework](https://symfony.com/). | `messages.en.yaml`, `messages.de.yaml` | +| XLIFF | `*.xlf`, `*.xliff` | Supports source/target translations in XLIFF files (used e.g. within [TYPO3 CMS](https://typo3.org/)). | `locallang.xlf`, `de.locallang.xlf` | +| YAML | `*.yml`, `*.yaml` | Supports YAML files (used e.g. within [Symfony Framework](https://symfony.com/)). | `messages.en.yaml`, `messages.de.yaml` |
69-69: Use idiomatic phrasing for American English-Please have a look at [`CONTRIBUTING.md`](CONTRIBUTING.md). +Please take a look at [`CONTRIBUTING.md`](CONTRIBUTING.md).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
docs/console.jpgis excluded by!**/*.jpgdocs/console.pngis excluded by!**/*.png
📒 Files selected for processing (3)
CONTRIBUTING.md(1 hunks)README.md(1 hunks)src/Command/ValidateTranslationCommand.php(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- CONTRIBUTING.md
🚧 Files skipped from review as they are similar to previous changes (1)
- src/Command/ValidateTranslationCommand.php
🧰 Additional context used
🪛 LanguageTool
README.md
[uncategorized] ~13-~13: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...nd validate-translations to check for translations mismatches, duplicates and schema valid...
(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)
[style] ~54-~54: This phrase is redundant (‘L’ stands for ‘language’). Use simply “yaml”.
Context: ... Yaml | *.yml, *.yaml | Supports yaml language files. Used e.g. within [Symfony Framew...
(ACRONYM_TAUTOLOGY)
[locale-violation] ~69-~69: In American English, “take a look” is more commonly used.
Context: ... | ## 🧑💻 Contributing Please have a look at CONTRIBUTING.md...
(HAVE_A_LOOK)
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Chores