Skip to content

Commit

Permalink
Add ConstantToServiceCallRector (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
zoglo authored May 13, 2024
1 parent bdf77d0 commit 995a7e2
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 0 deletions.
6 changes: 6 additions & 0 deletions config/sets/contao/contao-413.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
use Contao\Controller;
use Contao\CoreBundle\Security\ContaoCorePermissions;
use Contao\Folder;
use Contao\Rector\Rector\ConstantToServiceCallRector;
use Contao\Rector\Rector\InsertTagsServiceRector;
use Contao\Rector\Rector\LegacyFrameworkCallToServiceCallRector;
use Contao\Rector\Rector\SystemLanguagesToServiceRector;
use Contao\Rector\ValueObject\ConstantToServiceCall;
use Contao\Rector\ValueObject\LegacyFrameworkCallToServiceCall;
use Contao\StringUtil;
use Patchwork\Utf8;
Expand Down Expand Up @@ -72,6 +74,10 @@
// Contao 4.13
$rectorConfig->rule(InsertTagsServiceRector::class);

$rectorConfig->ruleWithConfiguration(ConstantToServiceCallRector::class, [
new ConstantToServiceCall('REQUEST_TOKEN', 'contao.csrf.token_manager', 'getDefaultTokenValue'),
]);

// Contao 4.12
//'Contao\FrontendUser::isMemberOf($ids)' => 'Contao\System::getContainer()->get(\'security.helper\')->isGranted(ContaoCorePermissions::MEMBER_IN_GROUPS, $ids)',
};
66 changes: 66 additions & 0 deletions src/Rector/ConstantToServiceCallRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace Contao\Rector\Rector;

use Contao\Rector\ValueObject\ConstantToServiceCall;
use PhpParser\Node;
use Rector\Contract\Rector\ConfigurableRectorInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use Webmozart\Assert\Assert;

final class ConstantToServiceCallRector extends AbstractLegacyFrameworkCallRector implements ConfigurableRectorInterface
{
/**
* @var array<ConstantToServiceCall>
*/
private array $configuration;

public function configure(array $configuration): void
{
Assert::allIsAOf($configuration, ConstantToServiceCall::class);
$this->configuration = $configuration;
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Fixes deprecated constants to service calls', [
new CodeSample(
<<<'CODE_BEFORE'
$requestToken = REQUEST_TOKEN;
CODE_BEFORE
,
<<<'CODE_AFTER'
$requestToken = \Contao\System::getContainer()->get('contao.csrf.token_manager')->getDefaultTokenValue();
CODE_AFTER
),
]);
}

public function getNodeTypes(): array
{
return [
Node\Expr\ConstFetch::class,
];
}

public function refactor(Node $node): ?Node
{
assert($node instanceof Node\Expr\ConstFetch);

foreach ($this->configuration as $config) {
if ($this->isName($node->name, $config->getConstant())) {
$container = new Node\Expr\StaticCall(new Node\Name\FullyQualified('Contao\System'), 'getContainer');
$service = new Node\Expr\MethodCall($container, 'get', [new Node\Arg(new Node\Scalar\String_($config->getServiceName()))]);
$method_name = new Node\Identifier($config->getServiceMethodName());
$node = new Node\Expr\MethodCall($service, $method_name);

return $node;
}
}

return null;
}
}
30 changes: 30 additions & 0 deletions src/ValueObject/ConstantToServiceCall.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Contao\Rector\ValueObject;

class ConstantToServiceCall
{
public function __construct(
private readonly string $constant,
private readonly string $serviceName,
private readonly string $serviceMethodName
) {
}

public function getConstant(): string
{
return $this->constant;
}

public function getServiceName(): string
{
return $this->serviceName;
}

public function getServiceMethodName(): string
{
return $this->serviceMethodName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Contao\Rector\Tests\Rector\ConstantToServiceCallRector;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class ConstantToServiceCallRectorTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/config.php';
}
}
13 changes: 13 additions & 0 deletions tests/Rector/ConstantToServiceCallRector/config/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

use Contao\Rector\Rector\ConstantToServiceCallRector;
use Contao\Rector\ValueObject\ConstantToServiceCall;
use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->ruleWithConfiguration(ConstantToServiceCallRector::class, [
new ConstantToServiceCall('REQUEST_TOKEN', 'contao.csrf.token_manager', 'getDefaultTokenValue')
]);
};
21 changes: 21 additions & 0 deletions tests/Rector/ConstantToServiceCallRector/fixture/constants.php.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

class Foo extends Controller
{
public function bar()
{
$requestToken = REQUEST_TOKEN;
}
}
?>
-----
<?php

class Foo extends Controller
{
public function bar()
{
$requestToken = \Contao\System::getContainer()->get('contao.csrf.token_manager')->getDefaultTokenValue();
}
}
?>

0 comments on commit 995a7e2

Please sign in to comment.