Skip to content

Commit

Permalink
[FEATURE] Add MigrateExpressionBuilderTrimMethodSecondParameterRector
Browse files Browse the repository at this point in the history
Resolves: #4091
  • Loading branch information
sabbelasichon committed Mar 10, 2024
1 parent 486be82 commit edd7223
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 7 deletions.
1 change: 1 addition & 0 deletions config/v13/typo3-130.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,5 @@
$rectorConfig->singleton(\Ssch\TYPO3Rector\TYPO313\v0\StrictTypesPersistenceManagerRector::class);
$rectorConfig->singleton(\Ssch\TYPO3Rector\TYPO313\v0\UseStrictTypesInExtbaseActionControllerRector::class);
$rectorConfig->rule(\Ssch\TYPO3Rector\TYPO313\v0\IntroduceCapabilitiesBitSetRector::class);
$rectorConfig->rule(\Ssch\TYPO3Rector\TYPO313\v0\MigrateExpressionBuilderTrimMethodSecondParameterRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php

declare(strict_types=1);

namespace Ssch\TYPO3Rector\TYPO313\v0;

use Doctrine\DBAL\Platforms\TrimMode;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Type\ObjectType;
use Rector\PhpParser\Node\Value\ValueResolver;
use Rector\Rector\AbstractRector;
use Rector\ValueObject\PhpVersionFeature;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @changelog https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/13.0/Breaking-102875-ExpressionBuilderChanges.html
* @see \Ssch\TYPO3Rector\Tests\Rector\v13\v0\MigrateExpressionBuilderTrimMethodSecondParameterRector\MigrateExpressionBuilderTrimMethodSecondParameterRectorTest
*/
final class MigrateExpressionBuilderTrimMethodSecondParameterRector extends AbstractRector implements MinPhpVersionInterface
{
/**
* @var array<int, string>
*/
private static array $integerToTrimMode = [
0 => 'UNSPECIFIED',
1 => 'LEADING',
2 => 'TRAILING',
3 => 'BOTH',
];

/**
* @readonly
*/
private ValueResolver $valueResolver;

public function __construct(ValueResolver $valueResolver)
{
$this->valueResolver = $valueResolver;
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Migrate second parameter of trim method to enum', [new CodeSample(
<<<'CODE_SAMPLE'
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('tt_content');
$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim($fieldName, 1),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('tt_content');
$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim($fieldName, TrimMode::LEADING),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);
CODE_SAMPLE
)]);
}

public function getNodeTypes(): array
{
return [MethodCall::class];
}

/**
* @param MethodCall $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->isName($node->name, 'trim')) {
return null;
}

if (! $this->nodeTypeResolver->isMethodStaticCallOrClassMethodObjectType(
$node,
new ObjectType('TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder')
)) {
return null;
}

$secondArgument = $node->args[1] ?? null;

if ($secondArgument === null) {
return null;
}

$trimMode = $this->valueResolver->getValue($secondArgument->value);

if (! is_int($trimMode)) {
return null;
}

if (! isset(self::$integerToTrimMode[$trimMode])) {
return null;
}

$trimModeConstant = self::$integerToTrimMode[$trimMode];

$node->args[1]->value = $this->nodeFactory->createClassConstFetch(TrimMode::class, $trimModeConstant);

Check failure on line 106 in rules/TYPO313/v0/MigrateExpressionBuilderTrimMethodSecondParameterRector.php

View workflow job for this annotation

GitHub Actions / 7.4 PHPStan

Class Doctrine\DBAL\Platforms\TrimMode not found.

Check failure on line 106 in rules/TYPO313/v0/MigrateExpressionBuilderTrimMethodSecondParameterRector.php

View workflow job for this annotation

GitHub Actions / 8 PHPStan

Class Doctrine\DBAL\Platforms\TrimMode not found.

return $node;
}

public function provideMinPhpVersion(): int
{
return PhpVersionFeature::ENUM;
}
}
16 changes: 16 additions & 0 deletions stubs/Doctrine/DBAL/Platforms/TrimMode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);

namespace Doctrine\DBAL\Platforms;

if(enum_exists('Doctrine\DBAL\Platforms\TrimMode')) {
return;
}

enum TrimMode: int
{
case UNSPECIFIED = 0;
case LEADING = 1;
case TRAILING = 2;
case BOTH = 3;
}
20 changes: 13 additions & 7 deletions stubs/TYPO3/CMS/Core/Database/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,30 @@
namespace TYPO3\CMS\Core\Database;

use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;

if (class_exists('TYPO3\CMS\Core\Database\Connection')) {
return;
}

class Connection extends \Doctrine\DBAL\Connection
{
/** @var ExpressionBuilder */
protected $_expr;
const PARAM_STR = 'string';
protected ExpressionBuilder $_expr;

/**
* @return ExpressionBuilder
*/
public function getExpressionBuilder()
public function getExpressionBuilder(): ExpressionBuilder
{
return $this->_expr;
}

public function createQueryBuilder(): QueryBuilder
{
}

public function lastInsertId()
{}
{

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

class ExpressionBuilder
{
const EQ = 1;

public function eq(string $fieldName, $value): string
{
return '';
Expand All @@ -30,4 +32,13 @@ public function and(...$expressions): void
public function or(...$expressions): void
{
}

public function comparison($trim, int $EQ, string $createNamedParameter)
{
}

public function trim(string $string, int $int): string
{
return '';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\v13\v0\MigrateExpressionBuilderTrimMethodSecondParameterRector\Fixture;

use Doctrine\DBAL\Platforms\TrimMode;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
use TYPO3\CMS\Core\Utility\GeneralUtility;

$queryBuilder = GeneralUtility::makeInstance(Connection::class)->createQueryBuilder();
$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', 0),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', 1),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', 2),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', 3),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', 5),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', TrimMode::LEADING),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

?>
-----
<?php

namespace Ssch\TYPO3Rector\Tests\Rector\v13\v0\MigrateExpressionBuilderTrimMethodSecondParameterRector\Fixture;

use Doctrine\DBAL\Platforms\TrimMode;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
use TYPO3\CMS\Core\Utility\GeneralUtility;

$queryBuilder = GeneralUtility::makeInstance(Connection::class)->createQueryBuilder();
$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', TrimMode::UNSPECIFIED),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', TrimMode::LEADING),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', TrimMode::TRAILING),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', TrimMode::BOTH),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', 5),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

$queryBuilder->expr()->comparison(
$queryBuilder->expr()->trim('string', TrimMode::LEADING),
ExpressionBuilder::EQ,
$queryBuilder->createNamedParameter('', Connection::PARAM_STR)
);

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

declare(strict_types=1);

namespace Ssch\TYPO3Rector\Tests\Rector\v13\v0\MigrateExpressionBuilderTrimMethodSecondParameterRector;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class MigrateExpressionBuilderTrimMethodSecondParameterRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

/**
* @return Iterator<array<string>>
*/
public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
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\TYPO313\v0\MigrateExpressionBuilderTrimMethodSecondParameterRector;

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

0 comments on commit edd7223

Please sign in to comment.