For coders TYPO3 Tech Corner

[TYPO3] Use rector to automatically update old extensions

[TYPO3] Use rector to automatically update old extensions

Note: Post last updated on September 10, 2022

I think that many of us have already faced the hurdle of getting an old extension that is no longer maintained for a new TYPO3 version to work again. Sometimes this is a lot of manual work. There is an automated solution for this with the PHP package ssch/rector, which can make changes to the code of extensions directly.

Rector: Installation and configuration

You can simply install rector for TYPO3 via composer:

composer require --dev ssch/typo3-rector

Then you can have a configuration file for TYPO3 created automatically:

cp ./vendor/ssch/typo3-rector/templates/rector.php.dist rector.php

This file (rector.php) is now in your project root directory. Here you can still set which changes in the code of your extension should be checked for. The set lists and the individual services that can be loaded are particularly important. The following is a greatly simplified example of a configuration of a TYPO3 extension that was created for TYPO3 8, but is now required in TYPO3 10:

<?php // rector.php declare(strict_types=1); use Rector\Config\RectorConfig; use Rector\Core\Configuration\Option; use Rector\Core\ValueObject\PhpVersion; use Ssch\TYPO3Rector\Configuration\Typo3Option; use Ssch\TYPO3Rector\FileProcessor\Composer\Rector\ExtensionComposerRector; use Ssch\TYPO3Rector\Rector\General\ConvertImplicitVariablesToExplicitGlobalsRector; use Ssch\TYPO3Rector\Rector\General\ExtEmConfRector; use Ssch\TYPO3Rector\Set\Typo3LevelSetList; return static function (RectorConfig $rectorConfig): void { $rectorConfig->sets([ Typo3LevelSetList::UP_TO_TYPO3_11 ]); // In order to have a better analysis from phpstan we teach it here some more things $rectorConfig->phpstanConfig(Typo3Option::PHPSTAN_FOR_RECTOR_PATH); // FQN classes are not imported by default. If you don't do it manually after every Rector run, enable it by: $rectorConfig->importNames(); // Disable parallel otherwise non php file processing is not working i.e. typoscript $rectorConfig->disableParallel(); // this will not import root namespace classes, like \DateTime or \Exception $rectorConfig->disableImportShortClasses(); // Define your target version which you want to support $rectorConfig->phpVersion(PhpVersion::PHP_74); // If you only want to process one/some TYPO3 extension(s), you can specify its path(s) here. // If you use the option --config change __DIR__ to getcwd() // $rectorConfig->paths([ // __DIR__ . '/packages/acme_demo/', // ]); // When you use rector there are rules that require some more actions like creating UpgradeWizards for outdated TCA types. // To fully support you we added some warnings. So watch out for them. // If you use importNames(), you should consider excluding some TYPO3 files. $rectorConfig->skip([ // @see <a href="https://github.com/sabbelasichon/typo3-rector/issues/2536" target="_blank" rel="noreferrer">github.com/sabbelasichon/typo3-rector/issues/2536</a> __DIR__ . '/**/Configuration/ExtensionBuilder/*', // We skip those directories on purpose as there might be node_modules or similar // that include typescript which would result in false positive processing __DIR__ . '/**/Resources/**/node_modules/*', __DIR__ . '/**/Resources/**/NodeModules/*', __DIR__ . '/**/Resources/**/BowerComponents/*', __DIR__ . '/**/Resources/**/bower_components/*', __DIR__ . '/**/Resources/**/build/*', __DIR__ . '/vendor/*', __DIR__ . '/Build/*', __DIR__ . '/public/*', __DIR__ . '/.github/*', __DIR__ . '/.Build/*', ]); // If you have trouble that rector cannot run because some TYPO3 constants are not defined add an additional constants file // @see <a href="https://github.com/sabbelasichon/typo3-rector/blob/master/typo3.constants.php" target="_blank" rel="noreferrer">github.com/sabbelasichon/typo3-rector/blob/master/typo3.constants.php</a> // @see <a href="https://github.com/rectorphp/rector/blob/main/docs/static_reflection_and_autoload.md#include-files" target="_blank" rel="noreferrer">github.com/rectorphp/rector/blob/main/docs/static_reflection_and_autoload.md</a> // $rectorConfig->bootstrapFiles([ // __DIR__ . '/typo3.constants.php' //]); // register a single rule // $rectorConfig->rule(\Ssch\TYPO3Rector\Rector\v9\v0\InjectAnnotationRector::class); /** * Useful rule from RectorPHP itself to transform i.e. GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager') * to GeneralUtility::makeInstance(\TYPO3\CMS\Core\Log\LogManager::class) calls. * But be warned, sometimes it produces false positives (edge cases), so watch out */ // $rectorConfig->rule(\Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class); // Optional non-php file functionalities: // @see <a href="https://github.com/sabbelasichon/typo3-rector/blob/main/docs/beyond_php_file_processors.md" target="_blank" rel="noreferrer">github.com/sabbelasichon/typo3-rector/blob/main/docs/beyond_php_file_processors.md</a> // Adapt your composer.json dependencies to the latest available version for the defined SetList // $rectorConfig->sets([ // Typo3SetList::COMPOSER_PACKAGES_104_CORE, // Typo3SetList::COMPOSER_PACKAGES_104_EXTENSIONS, // ]); // Rewrite your extbase persistence class mapping from typoscript into php according to official docs. // This processor will create a summarized file with all the typoscript rewrites combined into a single file. /* $rectorConfig->ruleWithConfiguration(\Ssch\TYPO3Rector\FileProcessor\TypoScript\Rector\v10\v0\ExtbasePersistenceTypoScriptRector::class, [ \Ssch\TYPO3Rector\FileProcessor\TypoScript\Rector\v10\v0\ExtbasePersistenceTypoScriptRector::FILENAME => __DIR__ . '/packages/acme_demo/Configuration/Extbase/Persistence/Classes.php', ]); */ // Add some general TYPO3 rules $rectorConfig->rule(ConvertImplicitVariablesToExplicitGlobalsRector::class); $rectorConfig->ruleWithConfiguration(ExtEmConfRector::class, [ ExtEmConfRector::ADDITIONAL_VALUES_TO_BE_REMOVED => [] ]); $rectorConfig->ruleWithConfiguration(ExtensionComposerRector::class, [ ExtensionComposerRector::TYPO3_VERSION_CONSTRAINT => '' ]); // Modernize your TypoScript include statements for files and move from <INCLUDE /> to @import use the FileIncludeToImportStatementVisitor (introduced with TYPO3 9.0) // $rectorConfig->rule(\Ssch\TYPO3Rector\FileProcessor\TypoScript\Rector\v9\v0\FileIncludeToImportStatementTypoScriptRector::class); };

And you can have your files updated automatically:

# Test which files can be changed ./vendor/bin/rector process private/typo3conf/ext/extensionkey --dry-run # Change files now ./vendor/bin/rector process private/typo3conf/ext/extensionkey

Rector: Best practice

Without a doubt, Rector is a great piece of software that is being improved every day. Using it can save you hours of tinkering, research and, above all, trial and error.

Nevertheless, it is possible that tomorrow a new rule will be added that is still missing today. In addition, you may have to live with the fact that not every line of code can be converted automatically. For some methods, there may be several ways in which manual intervention is required. Other substitutions may not be as perfect as you would like them to be.

We therefore suggest a combination of automated and manual revision. With the help of GIT you can, for example, commit your changes in the extension. So if automatic adjustments are made afterwards, you can control the changes in your IDE and accept or roll back. For example, PhpStorm shows you exactly what has been changed.

Back

"Code faster, look at the time" - does this sound familiar to you?

How about time and respect for code quality? Working in a team? Automated tests?

Join us