Skip to content

Commit

Permalink
[FEATURE] Add MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector
Browse files Browse the repository at this point in the history
Resolves: #4236
  • Loading branch information
simonschaufi committed Apr 17, 2024
1 parent 713ddbe commit a7e9e8e
Show file tree
Hide file tree
Showing 11 changed files with 351 additions and 4 deletions.
2 changes: 2 additions & 0 deletions config/code-quality.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Ssch\TYPO3Rector\CodeQuality\General\InjectMethodToConstructorInjectionRector;
use Ssch\TYPO3Rector\CodeQuality\General\MoveExtensionManagementUtilityAddStaticFileIntoTCAOverridesRector;
use Ssch\TYPO3Rector\CodeQuality\General\MoveExtensionManagementUtilityAddToAllTCAtypesIntoTCAOverridesRector;
use Ssch\TYPO3Rector\CodeQuality\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector;
use Ssch\TYPO3Rector\CodeQuality\General\UseExtensionKeyInLocalizationUtilityRector;

return static function (RectorConfig $rectorConfig): void {
Expand Down Expand Up @@ -48,5 +49,6 @@
$rectorConfig->rule(InjectMethodToConstructorInjectionRector::class);
$rectorConfig->rule(MoveExtensionManagementUtilityAddStaticFileIntoTCAOverridesRector::class);
$rectorConfig->rule(MoveExtensionManagementUtilityAddToAllTCAtypesIntoTCAOverridesRector::class);
$rectorConfig->rule(MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector::class);
$rectorConfig->rule(UseExtensionKeyInLocalizationUtilityRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<?php

declare(strict_types=1);

namespace Ssch\TYPO3Rector\CodeQuality\General;

use PhpParser\Node;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Expression;
use PhpParser\NodeTraverser;
use PHPStan\Type\ObjectType;
use Rector\PhpParser\Printer\BetterStandardPrinter;
use Rector\Rector\AbstractRector;
use Ssch\TYPO3Rector\ComposerExtensionKeyResolver;
use Ssch\TYPO3Rector\Contract\FilesystemInterface;
use Ssch\TYPO3Rector\Filesystem\FilesFinder;
use Ssch\TYPO3Rector\Helper\ExtensionKeyResolverTrait;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @changelog https://review.typo3.org/c/Packages/TYPO3.CMS/+/52437
* @see \Ssch\TYPO3Rector\Tests\Rector\CodeQuality\Rector\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRectorTest
*/
final class MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector extends AbstractRector
{
use ExtensionKeyResolverTrait;

/**
* @readonly
*/
private FilesFinder $filesFinder;

/**
* @readonly
*/
private FilesystemInterface $filesystem;

/**
* @readonly
*/
private BetterStandardPrinter $betterStandardPrinter;

public function __construct(
FilesFinder $filesFinder,
FilesystemInterface $filesystem,
ComposerExtensionKeyResolver $composerExtensionKeyResolver,
BetterStandardPrinter $betterStandardPrinter
) {
$this->filesFinder = $filesFinder;
$this->filesystem = $filesystem;
$this->composerExtensionKeyResolver = $composerExtensionKeyResolver;
$this->betterStandardPrinter = $betterStandardPrinter;
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Move ExtensionUtility::registerPlugin into Configuration/TCA/Overrides/tt_content.php',
[
new CodeSample(
<<<'CODE_SAMPLE'
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin('extension_key', 'Pi1', 'Title');
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
// Move to file Configuration/TCA/Overrides/tt_content.php
CODE_SAMPLE
),
]
);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Expression::class];
}

/**
* @param Expression $node
*/
public function refactor(Node $node)
{
$staticMethodCall = $node->expr;
if (! $staticMethodCall instanceof StaticCall) {
return null;
}

if ($this->shouldSkip($staticMethodCall)) {
return null;
}

$contentArgument = $staticMethodCall->args[0] ?? null;
if ($contentArgument === null) {
return null;
}

$contentArgumentValue = $contentArgument->value;
if (! $contentArgumentValue instanceof String_ && ! $contentArgumentValue instanceof Variable) {
return null;
}

$extensionKey = $this->resolvePotentialExtensionKeyByExtensionKeyParameter($contentArgumentValue);
if ($extensionKey instanceof String_) {
$contentArgument->value = $extensionKey;
}

$content = $this->betterStandardPrinter->prettyPrint([$staticMethodCall]) . ';';

$directoryName = dirname($this->file->getFilePath());
$newConfigurationFile = $directoryName . '/Configuration/TCA/Overrides/tt_content.php';
if ($this->filesystem->fileExists($newConfigurationFile)) {
$this->filesystem->appendToFile($newConfigurationFile, $content . PHP_EOL);
} else {
$this->filesystem->write($newConfigurationFile, <<<CODE
<?php
{$content}
CODE
);
}

return NodeTraverser::REMOVE_NODE;
}

private function shouldSkip(StaticCall $staticMethodCall): bool
{
if (! $this->nodeTypeResolver->isMethodStaticCallOrClassMethodObjectType(
$staticMethodCall,
new ObjectType('TYPO3\CMS\Extbase\Utility\ExtensionUtility')
)) {
return true;
}

if (! $this->isName($staticMethodCall->name, 'registerPlugin')) {
return true;
}

return ! $this->filesFinder->isExtTables($this->file->getFilePath());
}
}
5 changes: 1 addition & 4 deletions stubs/TYPO3/CMS/Extbase/Utility/ExtensionUtility.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ class ExtensionUtility
*/
const PLUGIN_TYPE_CONTENT_ELEMENT = 'CType';

/**
* @return void
*/
public static function registerPlugin($extensionName, $pluginName, $pluginTitle, $pluginIcon = null)
public static function registerPlugin($extensionName, $pluginName, $pluginTitle, $pluginIcon = null, $group = 'default', string $pluginDescription = ''): string
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin('extension1', 'PluginName', 'My Title');
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

# tt_content.php file exists

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin('extension2', 'PluginName', 'My Title');
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin('extension3', 'PluginName', 'My Title');

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin('extension3', 'Pi3', 'My Title');
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\CodeQuality\Rector\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector\Fixture;

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin('extension1', 'PluginName', 'My Title');
?>
-----
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\CodeQuality\Rector\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector\Fixture;

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\CodeQuality\Rector\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector\Fixture;

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin('extension2', 'PluginName', 'My Title');
?>
-----
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\CodeQuality\Rector\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector\Fixture;

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\CodeQuality\Rector\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector\Fixture;

$_EXTKEY = 'extension3';

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin($_EXTKEY, 'PluginName', 'My Title');
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin('extension3', 'Pi3', 'My Title');
// Once the rule RegisterPluginWithVendorNameRector does its job, we can move it afterwards
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin('Vendor.' . $_EXTKEY, 'PluginName', 'My Title');

?>
-----
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\CodeQuality\Rector\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector\Fixture;

use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
$_EXTKEY = 'extension3';
// Once the rule RegisterPluginWithVendorNameRector does its job, we can move it afterwards
ExtensionUtility::registerPlugin('Vendor.' . $_EXTKEY, 'PluginName', 'My Title');

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

declare(strict_types=1);

namespace Ssch\TYPO3Rector\Tests\Rector\CodeQuality\Rector\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Ssch\TYPO3Rector\Contract\FilesystemInterface;

final class MoveExtensionUtilityRegisterPluginIntoTCAOverridesRectorTest extends AbstractRectorTestCase
{
private FilesystemInterface $filesystem;

/**
* @var string[]
*/
private array $testFilesToDelete = [];

protected function setUp(): void
{
parent::setUp();
$this->initializeFilesystem();
}

protected function tearDown(): void
{
foreach ($this->testFilesToDelete as $filename) {
$this->filesystem->delete($filename);
}

parent::tearDown();
}

/**
* @dataProvider provideData
*/
public function testWithNonExistingComposerJson(
string $extensionKey,
?string $existingSysTemplateContent = null
): void {
// Arrange
if ($existingSysTemplateContent !== null) {
$sysTemplate = __DIR__ . '/Fixture/' . $extensionKey . '/Configuration/TCA/Overrides/tt_content.php';
$this->testFilesToDelete[] = $sysTemplate;
$this->filesystem->write($sysTemplate, $existingSysTemplateContent);
}

// Act
$this->doTestFile(__DIR__ . '/Fixture/' . $extensionKey . '/ext_tables.php.inc');
$this->testFilesToDelete[] = __DIR__ . '/Fixture/' . $extensionKey . '/Configuration/TCA/Overrides/tt_content.php';

// Assert
$content = $this->filesystem->read(
__DIR__ . '/Fixture/' . $extensionKey . '/Configuration/TCA/Overrides/tt_content.php'
);
self::assertStringEqualsFile(
__DIR__ . '/Assertions/' . $extensionKey . '/Configuration/TCA/Overrides/tt_content.php',
$content
);
}

/**
* @dataProvider provideData
*/
public function testWithExistingComposerJson(string $extensionKey, ?string $existingSysTemplateContent = null): void
{
// Arrange
$composerJson = __DIR__ . '/Fixture/' . $extensionKey . '/composer.json';
$this->testFilesToDelete[] = $composerJson;
$this->filesystem->write($composerJson, '{
"extra": {
"typo3/cms": {
"extension-key": "' . $extensionKey . '"
}
}
}
');

if ($existingSysTemplateContent !== null) {
$sysTemplate = __DIR__ . '/Fixture/' . $extensionKey . '/Configuration/TCA/Overrides/tt_content.php';
$this->testFilesToDelete[] = $sysTemplate;
$this->filesystem->write($sysTemplate, $existingSysTemplateContent);
}

// Act
$this->doTestFile(__DIR__ . '/Fixture/' . $extensionKey . '/ext_tables.php.inc');
$this->testFilesToDelete[] = __DIR__ . '/Fixture/' . $extensionKey . '/Configuration/TCA/Overrides/tt_content.php';

// Assert
$content = $this->filesystem->read(
__DIR__ . '/Fixture/' . $extensionKey . '/Configuration/TCA/Overrides/tt_content.php'
);
self::assertStringEqualsFile(
__DIR__ . '/Assertions/' . $extensionKey . '/Configuration/TCA/Overrides/tt_content.php',
$content
);
}

/**
* @return Iterator<array<string>>
*/
public static function provideData(): Iterator
{
yield 'Test that new tt_content.php is created with correct content' => ['extension1'];

yield 'Test that content is appended to existing tt_content.php file' => [
'extension2',
'<?php
# tt_content.php file exists
',
];

yield 'Test that new tt_content.php is created with correct content but unresolvable content cannot be migrated properly' => [
'extension3',
];
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}

private function initializeFilesystem(): void
{
$this->filesystem = self::getContainer()
->get(FilesystemInterface::class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Ssch\TYPO3Rector\CodeQuality\General\MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->import(__DIR__ . '/../../../../../../../config/config_test.php');
$rectorConfig->rule(MoveExtensionUtilityRegisterPluginIntoTCAOverridesRector::class);
};

0 comments on commit a7e9e8e

Please sign in to comment.