Skip to content

Commit

Permalink
New rector (9.1): ClassConstantToClassConstantRector to rename class …
Browse files Browse the repository at this point in the history
…constants to a new class.
  • Loading branch information
bbrala committed Dec 31, 2023
1 parent 598834b commit de8330b
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 0 deletions.
24 changes: 24 additions & 0 deletions config/drupal-9/drupal-9.1-deprecations.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use DrupalRector\Drupal9\Rector\Deprecation\UiHelperTraitDrupalPostFormRector;
use DrupalRector\Drupal9\Rector\Deprecation\UserPasswordRector;
use DrupalRector\Drupal9\Rector\ValueObject\AssertLegacyTraitConfiguration;
use DrupalRector\Rector\Deprecation\ClassConstantToClassConstantRector;
use DrupalRector\Rector\ValueObject\ClassConstantToClassConstantConfiguration;
use DrupalRector\Services\AddCommentService;
use Rector\Config\RectorConfig;
use Rector\PHPUnit\Set\PHPUnitSetList;
Expand Down Expand Up @@ -107,4 +109,26 @@
'toNumber'
),
]);

// Change record: https://www.drupal.org/node/3151009 (only constants are supported)
$rectorConfig->ruleWithConfiguration(ClassConstantToClassConstantRector::class, [
new ClassConstantToClassConstantConfiguration(
'Symfony\Cmf\Component\Routing\RouteObjectInterface',
'ROUTE_NAME',
'Drupal\Core\Routing\RouteObjectInterface',
'ROUTE_NAME',
),
new ClassConstantToClassConstantConfiguration(
'Symfony\Cmf\Component\Routing\RouteObjectInterface',
'ROUTE_OBJECT',
'Drupal\Core\Routing\RouteObjectInterface',
'ROUTE_OBJECT',
),
new ClassConstantToClassConstantConfiguration(
'Symfony\Cmf\Component\Routing\RouteObjectInterface',
'CONTROLLER_NAME',
'Drupal\Core\Routing\RouteObjectInterface',
'CONTROLLER_NAME',
),
]);
};
112 changes: 112 additions & 0 deletions src/Rector/Deprecation/ClassConstantToClassConstantRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

declare(strict_types=1);

namespace DrupalRector\Rector\Deprecation;

use DrupalRector\Rector\ValueObject\ClassConstantToClassConstantConfiguration;
use DrupalRector\Rector\ValueObject\ConstantToClassConfiguration;
use PhpParser\Node;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* Replaces deprecated constant with class constant.
*
* What is covered:
* - Replacement with a use statement.
*/
class ClassConstantToClassConstantRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @var ClassConstantToClassConstantConfiguration[]
*/
private array $constantToClassRenames;

public function configure(array $configuration): void
{
foreach ($configuration as $value) {
if (!($value instanceof ClassConstantToClassConstantConfiguration)) {
throw new \InvalidArgumentException(sprintf('Each configuration item must be an instance of "%s"', ConstantToClassConfiguration::class));
}
}

$this->constantToClassRenames = $configuration;
}

/**
* {@inheritdoc}
*/
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Fixes deprecated class contant use, used in Drupal 9.1 deprecations', [
new ConfiguredCodeSample(
<<<'CODE_BEFORE'
$value = Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_NAME;
$value2 = Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_OBJECT;
$value3 = Symfony\Cmf\Component\Routing\RouteObjectInterface::CONTROLLER_NAME;
CODE_BEFORE
,
<<<'CODE_AFTER'
$value = \Drupal\Core\Routing\RouteObjectInterface::ROUTE_NAME;
$value2 = \Drupal\Core\Routing\RouteObjectInterface::ROUTE_OBJECT;
$value3 = \Drupal\Core\Routing\RouteObjectInterface::CONTROLLER_NAME;
CODE_AFTER
,
[
new ClassConstantToClassConstantConfiguration(
'Symfony\Cmf\Component\Routing\RouteObjectInterface',
'ROUTE_NAME',
'Drupal\Core\Routing\RouteObjectInterface',
'ROUTE_NAME',
),
new ClassConstantToClassConstantConfiguration(
'Symfony\Cmf\Component\Routing\RouteObjectInterface',
'ROUTE_OBJECT',
'Drupal\Core\Routing\RouteObjectInterface',
'ROUTE_OBJECT',
),
new ClassConstantToClassConstantConfiguration(
'Symfony\Cmf\Component\Routing\RouteObjectInterface',
'CONTROLLER_NAME',
'Drupal\Core\Routing\RouteObjectInterface',
'CONTROLLER_NAME',
),
]
),
]);
}

/**
* {@inheritdoc}
*/
public function getNodeTypes(): array
{
return [
Node\Expr\ClassConstFetch::class,
];
}

/**
* {@inheritdoc}
*/
public function refactor(Node $node): ?Node
{
assert($node instanceof Node\Expr\ClassConstFetch);

foreach ($this->constantToClassRenames as $constantToClassRename) {
if ($this->getName($node->name) === $constantToClassRename->getDeprecated() && $this->getName($node->class) === $constantToClassRename->getDeprecatedClass()) {
// We add a fully qualified class name and the parameters in `rector.php` adds the use statement.
$fully_qualified_class = new Node\Name\FullyQualified($constantToClassRename->getClass());

$name = new Node\Identifier($constantToClassRename->getConstant());

return new Node\Expr\ClassConstFetch($fully_qualified_class, $name);
}
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace DrupalRector\Rector\ValueObject;

use Rector\Core\Validation\RectorAssert;

final class ClassConstantToClassConstantConfiguration
{
private string $deprecated;
private string $class;
private string $constant;

private string $deprecatedClass;

public function __construct(string $deprecatedClass, string $deprecated, string $class, string $constant)
{
$this->deprecatedClass = $deprecatedClass;
$this->deprecated = $deprecated;
$this->class = $class;
$this->constant = $constant;

RectorAssert::className($deprecatedClass);
RectorAssert::className($class);
RectorAssert::constantName($deprecated);
RectorAssert::constantName($constant);
}

public function getDeprecated(): string
{
return $this->deprecated;
}

public function getClass(): string
{
return $this->class;
}

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

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

declare(strict_types=1);

namespace DrupalRector\Rector\Deprecation\ClassConstantToClassConstantRector;

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

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

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

public function provideConfigFilePath(): string
{
// must be implemented
return __DIR__.'/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

use DrupalRector\Rector\Deprecation\ClassConstantToClassConstantRector;
use DrupalRector\Rector\ValueObject\ClassConstantToClassConstantConfiguration;
use DrupalRector\Tests\Rector\Deprecation\DeprecationBase;
use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
DeprecationBase::addClass(ClassConstantToClassConstantRector::class, $rectorConfig, false, [
new ClassConstantToClassConstantConfiguration(
'Symfony\Cmf\Component\Routing\RouteObjectInterface',
'ROUTE_NAME',
'Drupal\Core\Routing\RouteObjectInterface',
'ROUTE_NAME',
),
new ClassConstantToClassConstantConfiguration(
'Symfony\Cmf\Component\Routing\RouteObjectInterface',
'ROUTE_OBJECT',
'Drupal\Core\Routing\RouteObjectInterface',
'ROUTE_OBJECT',
),
new ClassConstantToClassConstantConfiguration(
'Symfony\Cmf\Component\Routing\RouteObjectInterface',
'CONTROLLER_NAME',
'Drupal\Core\Routing\RouteObjectInterface',
'CONTROLLER_NAME',
),
]);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

function simple_example() {
$value = Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_NAME;
$value2 = Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_OBJECT;
$value3 = Symfony\Cmf\Component\Routing\RouteObjectInterface::CONTROLLER_NAME;
}

?>
-----
<?php

function simple_example() {
$value = \Drupal\Core\Routing\RouteObjectInterface::ROUTE_NAME;
$value2 = \Drupal\Core\Routing\RouteObjectInterface::ROUTE_OBJECT;
$value3 = \Drupal\Core\Routing\RouteObjectInterface::CONTROLLER_NAME;
}

?>

0 comments on commit de8330b

Please sign in to comment.