rector/build/target-repository/docs/beyond_php_file_processors.md
Sebastian Schreiber 25821f6212
[TASK] Add documentation about FileProcessors (#121)
* [TASK] Add documentation about FileProcessors

Resolves: https://github.com/rectorphp/rector/issues/6374

* [TASK] Change some things
2021-06-13 13:19:16 +02:00

4.8 KiB
Raw Blame History

Beyond PHP - FileProcessors

You think Rector is all about PHP? You might be wrong. Sure, the vast majority of the rules included in Rector is for PHP-Code. That´s true.

But since version 0.11.x Rector introduced the concept of so called FileProcessors. When you are running Rector with the process command all collected files from your configured paths are iterated through all registered FileProcessors.

Each FileProcessor must implement the FileProcessorInterface and must decide if it is able to handle a given file by the supports method or not.

Rector itself already ships with three FileProcessors. Whereas the most important one, you guessed it, is the PhpFileProcessor.

But another nice one is the ComposerFileProcessor. The ComposerFileProcessor lets you manipulate composer.json files in your project. Let´s say you want to define a custom configuration where you want to update the version constraint of some packages. All you have to do is using the ChangePackageVersionComposerRector:

<?php
// rector.php
declare(strict_types=1);

use Rector\Composer\Rector\ChangePackageVersionComposerRector;
use Rector\Composer\ValueObject\PackageAndVersion;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\SymfonyPhpConfig\ValueObjectInliner;

return static function (ContainerConfigurator $containerConfigurator): void {
    $services = $containerConfigurator->services();
    $services->set(ChangePackageVersionComposerRector::class)
        ->call('configure', [[
            // we use constant for keys to save you from typos
            ChangePackageVersionComposerRector::PACKAGES_AND_VERSIONS  => ValueObjectInliner::inline([
                new PackageAndVersion('symfony/yaml', '^5.0'),
            ]),
        ]]);
};

There are some more rules related to manipulate your composer.json files. Let´s see them in action:

<?php
// rector.php
declare(strict_types=1);

use Rector\Composer\Rector\AddPackageToRequireComposerRector;
use Rector\Composer\Rector\AddPackageToRequireDevComposerRector;
use Rector\Composer\Rector\RemovePackageComposerRector;
use Rector\Composer\Rector\ReplacePackageAndVersionComposerRector;
use Rector\Composer\ValueObject\PackageAndVersion;
use Rector\Composer\ValueObject\ReplacePackageAndVersion;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\SymfonyPhpConfig\ValueObjectInliner;

return static function (ContainerConfigurator $containerConfigurator): void {
    $services = $containerConfigurator->services();

    // Add a package to the require section of your composer.json
    $services->set(AddPackageToRequireComposerRector::class)
        ->call('configure', [[
            // we use constant for keys to save you from typos
            AddPackageToRequireComposerRector::PACKAGES_AND_VERSIONS  => ValueObjectInliner::inline([
                new PackageAndVersion('symfony/yaml', '^5.0'),
            ]),
        ]]);

    // Add a package to the require dev section of your composer.json
    $services->set(AddPackageToRequireDevComposerRector::class)
        ->call('configure', [[
            // we use constant for keys to save you from typos
            AddPackageToRequireDevComposerRector::PACKAGES_AND_VERSIONS  => ValueObjectInliner::inline([
                new PackageAndVersion('phpunit/phpunit', '^9.0'),
            ]),
        ]]);

    // Remove a package from composer.json
    $services->set(RemovePackageComposerRector::class)
        ->call('configure', [[
            // we use constant for keys to save you from typos
            RemovePackageComposerRector::PACKAGE_NAMES  => ['symfony/console']
        ]]);

        // Replace a package in the composer.json
    $services->set(ReplacePackageAndVersionComposerRector::class)
        ->call('configure', [[
            // we use constant for keys to save you from typos
             ReplacePackageAndVersionComposerRector::REPLACE_PACKAGES_AND_VERSIONS => ValueObjectInliner::inline([
                new ReplacePackageAndVersion('vendor1/package2', 'vendor2/package1', '^3.0'),
            ]),
        ]]);
};

Behind every FileProcessor are one or multiple rules which are in turn implementing a dedicated Interface extending the RectorInterface. In the case of the ComposerFileProcessor all rules are implementing the ComposerRectorInterface

Are you eager to create your own one? Dive in and have a look at How to create a custom FileProcessor