diff --git a/composer.json b/composer.json index d418716..3334194 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ "require": { "php": ">=7.4", "friendsofphp/php-cs-fixer": "v3.75.0", - "adamwojs/php-cs-fixer-phpdoc-force-fqcn": "^2.0" + "adamwojs/php-cs-fixer-phpdoc-force-fqcn": "^2.0", + "composer-runtime-api": ">=2.0" }, "require-dev": { "roave/security-advisories": "dev-master", @@ -29,7 +30,7 @@ }, "autoload-dev": { "psr-4": { - "Ibexa\\Tests\\CodeStyle\\PhpCsFixer\\": "tests/lib/" + "Ibexa\\Tests\\CodeStyle\\": "tests/lib/" } }, "scripts": { diff --git a/src/lib/PhpCsFixer/InternalConfigFactory.php b/src/lib/PhpCsFixer/InternalConfigFactory.php index e9b6f87..2035fd9 100644 --- a/src/lib/PhpCsFixer/InternalConfigFactory.php +++ b/src/lib/PhpCsFixer/InternalConfigFactory.php @@ -8,6 +8,7 @@ namespace Ibexa\CodeStyle\PhpCsFixer; +use Composer\InstalledVersions; use Ibexa\CodeStyle\PhpCsFixer\Sets\RuleSetInterface; use PhpCsFixer\ConfigInterface; @@ -42,7 +43,31 @@ public function withRuleSet(RuleSetInterface $ruleSet): self public function getRuleSet(): RuleSetInterface { - return $this->ruleSet ??= new Sets\Ibexa46RuleSet(); + return $this->ruleSet ??= $this->createRuleSetFromPackage(InstalledVersions::getRootPackage()); + } + + /** + * @param array{name: string, version: string, pretty_version?: string} $package + */ + private function createRuleSetFromPackage(array $package): RuleSetInterface + { + if (!str_starts_with($package['name'], 'ibexa/')) { + return new Sets\Ibexa46RuleSet(); + } + + $version = $package['pretty_version'] ?? $package['version']; + if (str_starts_with($version, 'dev-') || $version === '*') { + return new Sets\Ibexa50RuleSet(); + } + + // Remove any suffix like -dev, -alpha, etc. + $version = (string)preg_replace('/-.*$/', '', $version); + + if (version_compare($version, '5.0.0', '>=')) { + return new Sets\Ibexa50RuleSet(); + } + + return new Sets\Ibexa46RuleSet(); } public function buildConfig(): ConfigInterface diff --git a/tests/lib/PhpCsFixer/InternalConfigFactoryTest.php b/tests/lib/PhpCsFixer/InternalConfigFactoryTest.php new file mode 100644 index 0000000..71ef115 --- /dev/null +++ b/tests/lib/PhpCsFixer/InternalConfigFactoryTest.php @@ -0,0 +1,93 @@ +factory = new InternalConfigFactory(); + $reflection = new ReflectionClass(InternalConfigFactory::class); + + // This method is private because we don't want it to be part of the public API. + // We can't test getRuleSet since it internally uses InstalledVersions::getRootPackage(), which cannot be mocked. + $this->createRuleSetFromPackage = $reflection->getMethod('createRuleSetFromPackage'); + $this->createRuleSetFromPackage->setAccessible(true); + } + + /** + * @dataProvider provideRuleSetTestCases + */ + public function testVersionBasedRuleSetSelection(array $package, string $expectedRuleSetClass): void + { + $ruleSet = $this->createRuleSetFromPackage->invoke($this->factory, $package); + + self::assertInstanceOf($expectedRuleSetClass, $ruleSet); + } + + public function provideRuleSetTestCases(): array + { + return [ + 'non_ibexa_package' => [ + ['name' => 'vendor/package', 'version' => '1.0.0'], + Ibexa46RuleSet::class, + ], + 'ibexa_package_4_6' => [ + ['name' => 'ibexa/core', 'version' => '4.6.0'], + Ibexa46RuleSet::class, + ], + 'ibexa_package_5_0' => [ + ['name' => 'ibexa/core', 'version' => '5.0.0'], + Ibexa50RuleSet::class, + ], + 'ibexa_package_5_1' => [ + ['name' => 'ibexa/core', 'version' => '5.1.0'], + Ibexa50RuleSet::class, + ], + 'ibexa_package_dev_master' => [ + ['name' => 'ibexa/core', 'version' => 'dev-master'], + Ibexa50RuleSet::class, + ], + 'ibexa_package_with_pretty_version' => [ + ['name' => 'ibexa/core', 'version' => '5.0.0', 'pretty_version' => '5.0.0-alpha1'], + Ibexa50RuleSet::class, + ], + 'ibexa_package_wildcard' => [ + ['name' => 'ibexa/core', 'version' => '*'], + Ibexa50RuleSet::class, + ], + 'ibexa_package_4_6_with_suffix' => [ + ['name' => 'ibexa/core', 'version' => '4.6.0-beta1'], + Ibexa46RuleSet::class, + ], + ]; + } + + public function testWithRuleSet(): void + { + $customRuleSet = new Ibexa46RuleSet(); + $this->factory->withRuleSet($customRuleSet); + + self::assertSame($customRuleSet, $this->factory->getRuleSet()); + } +} diff --git a/tests/lib/Sets/Ibexa46RuleSetTest.php b/tests/lib/PhpCsFixer/Sets/Ibexa46RuleSetTest.php similarity index 100% rename from tests/lib/Sets/Ibexa46RuleSetTest.php rename to tests/lib/PhpCsFixer/Sets/Ibexa46RuleSetTest.php diff --git a/tests/lib/Sets/Ibexa50RuleSetTest.php b/tests/lib/PhpCsFixer/Sets/Ibexa50RuleSetTest.php similarity index 100% rename from tests/lib/Sets/Ibexa50RuleSetTest.php rename to tests/lib/PhpCsFixer/Sets/Ibexa50RuleSetTest.php diff --git a/tests/lib/Sets/expected_rules/4_6_rule_set/local_rules.php b/tests/lib/PhpCsFixer/Sets/expected_rules/4_6_rule_set/local_rules.php similarity index 100% rename from tests/lib/Sets/expected_rules/4_6_rule_set/local_rules.php rename to tests/lib/PhpCsFixer/Sets/expected_rules/4_6_rule_set/local_rules.php diff --git a/tests/lib/Sets/expected_rules/4_6_rule_set/php_cs_fixer_rules.php b/tests/lib/PhpCsFixer/Sets/expected_rules/4_6_rule_set/php_cs_fixer_rules.php similarity index 100% rename from tests/lib/Sets/expected_rules/4_6_rule_set/php_cs_fixer_rules.php rename to tests/lib/PhpCsFixer/Sets/expected_rules/4_6_rule_set/php_cs_fixer_rules.php diff --git a/tests/lib/Sets/expected_rules/5_0_rule_set/local_rules.php b/tests/lib/PhpCsFixer/Sets/expected_rules/5_0_rule_set/local_rules.php similarity index 100% rename from tests/lib/Sets/expected_rules/5_0_rule_set/local_rules.php rename to tests/lib/PhpCsFixer/Sets/expected_rules/5_0_rule_set/local_rules.php diff --git a/tests/lib/Sets/expected_rules/5_0_rule_set/php_cs_fixer_rules.php b/tests/lib/PhpCsFixer/Sets/expected_rules/5_0_rule_set/php_cs_fixer_rules.php similarity index 100% rename from tests/lib/Sets/expected_rules/5_0_rule_set/php_cs_fixer_rules.php rename to tests/lib/PhpCsFixer/Sets/expected_rules/5_0_rule_set/php_cs_fixer_rules.php