YmlFixer is a command in the upgrade-toolkit
that applies predefined rules to YAML files located in the processed directory.
Each rule is defined in a separate class and applied sequentially.
The command runs automatically when php bin/upgrade-toolkit is executed but can also be run independently if needed:
php bin/upgrade-toolkit yml:fix
However, in most cases, you will not need to run it separately.
This overview explains how to create a basic YmlFixer rule by demonstrating the process of replacing one service argument with another.
- Create a class that implements the YmlFixerInterface
use Oro\UpgradeToolkit\YmlFixer\Contract\YmlFixerInterface;
class ExampleFixer implements YmlFixerInterface
{
#[\Override]
public function fix(array &$config): void
{
// The rule code
}
#[\Override]
public function matchFile(): string
{
// Returns file path glob pattern the rule should be applied to
}
}
- Define the glob pattern of the files that should be processed
...
#[\Override]
public function matchFile(): string
{
return '**/Resources/config/services.yml';
}
...
- Implement the rule Logic
Tip
The $config parameter in the fix method represents the array definition of the currently processed YAML file.
Below is an example of how to implement the logic to replace a service argument:
use Oro\UpgradeToolkit\YmlFixer\Config\YmlConfigKeys as Keys;
...
#[\Override]
public function fix(array &$config): void
{
foreach ($config[Keys::SERVICES] as $serviceName => $serviceDef) {
foreach ($serviceDef[Keys::ARGUMENTS] as $key => $argument) {
if ('@some_OLD_argument' === $argument)) {
$config[Keys::SERVICES][$serviceName][Keys::ARGUMENTS][$key] = '@some_NEW_argument';
}
}
}
}
...
Tip
Oro\UpgradeToolkit\YmlFixer\Config\YmlConfigKeys
contains most keys used in Oro YAML configurations.
- Add the rule to the configuration
Add the newly created rule to the config file located in the upgrade-toolkit/src/YmlFixer/Config/Config.php
file:
...
public function getRules(): array
{
return [
...
ExampleFixer::class,
];
}
...
Below is the full code for ExampleFixer
:
use Oro\UpgradeToolkit\YmlFixer\Config\YmlConfigKeys as Keys;
use Oro\UpgradeToolkit\YmlFixer\Contract\YmlFixerInterface;
class ExampleFixer implements YmlFixerInterface
{
#[\Override]
public function fix(array &$config): void
{
foreach ($config[Keys::SERVICES] as $serviceName => $serviceDef) {
foreach ($serviceDef[Keys::ARGUMENTS] as $key => $argument) {
if ('@some_OLD_argument' === $argument)) {
$config[Keys::SERVICES][$serviceName][Keys::ARGUMENTS][$key] = '@some_NEW_argument';
}
}
}
}
#[\Override]
public function matchFile(): string
{
return '**/Resources/config/services.yml';
}
}
It is strongly advised to create a test for newly added rules.
Below is an example of a test that could be written for the ExampleFixer
rule.
use Oro\UpgradeToolkit\YmlFixer\Testing\PHPUnit\AbstractYmlFixerTestCase;
class ExampleFixerTest extends AbstractYmlFixerTestCase
{
public function test(): void
{
$this->testRule(
ExampleFixer::class,
'path/to/fixture/before/the/rule/was/applied/services.yml',
'path/to/fixture/after/the/rule/was/applied/replaced_args_services.yml'
);
}
}
AbstractYmlFixerTestCase provides the method testRule
which requires:
- The class name of the tested rule
- Fixture files that contain the yml configs before and after the rule is applied
In some cases, it may be necessary to add rules that share similar logic and can be grouped together.
For example, renaming several services may be required.
This can be accomplished by adding configuration.
The simplest way is to add the __construct
and the config
methods to the rule code.
use Oro\UpgradeToolkit\YmlFixer\Contract\YmlFixerInterface;
class ExampleFixer implements YmlFixerInterface
{
public function __construct(
private ?array $ruleConfiguration = null,
) {
}
#[\Override]
public function fix(array &$config): void
{
// The rule code
}
#[\Override]
public function matchFile(): string
{
// Returns file path glob pattern the rule should be applied to
}
private function config(): array
{
return $this->ruleConfiguration ?? [
// Needed Configuration
];
}
}
The test should be structured as follows:
use Oro\UpgradeToolkit\YmlFixer\Testing\PHPUnit\AbstractYmlFixerTestCase;
class ExampleFixerTest extends AbstractYmlFixerTestCase
{
public function test(): void
{
$ruleConfiguration = [
// Test Configuration
];
$this->testRule(
ExampleFixer::class,
'path/to/fixture/before/the/rule/was/applied/services.yml',
'path/to/fixture/after/the/rule/was/applied/replaced_args_services.yml',
$ruleConfiguration
);
}
}
Complete examples of a rule with configuration and corresponding tests can be found in:
Oro\UpgradeToolkit\YmlFixer\Rules\Services\RenameServiceFixer
Oro\UpgradeToolkit\Tests\Unit\YmlFixer\Rules\Services\RenameServiceFixerTest