Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/contracts/Sets/ibexa-50.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace Ibexa\Contracts\Rector\Sets;

use Ibexa\Rector\Rule\ConstToEnumValueRector;
use Ibexa\Rector\Rule\PropertyToGetterRector;
use Ibexa\Rector\Rule\RemoveArgumentFromMethodCallRector;
use Rector\Config\RectorConfig;
Expand Down Expand Up @@ -226,4 +227,20 @@
'isContainer' => 'isContainer',
],
]);

$rectorConfig->ruleWithConfiguration(
ConstToEnumValueRector::class,
[
'Ibexa\Contracts\Core\Repository\Values\Content\Relation' => [
'enumClass' => 'Ibexa\Contracts\Core\Repository\Values\Content\RelationType',
'constants' => [
'COMMON' => 'COMMON',
'EMBED' => 'EMBED',
'LINK' => 'LINK',
'FIELD' => 'FIELD',
'ASSET' => 'ASSET',
],
],
]
);
};
98 changes: 98 additions & 0 deletions src/lib/Rule/ConstToEnumValueRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Rector\Rule;

use PhpParser\Node;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Name\FullyQualified;
use Rector\Contract\Rector\ConfigurableRectorInterface;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

final class ConstToEnumValueRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @var array<string, array{enumClass: string, constants: array<string>|null}>
*/
private array $transformationMap = [];

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Replace class constants with enum values (adds ->value)',
[
new ConfiguredCodeSample(
'OldClass::CONSTANT',
'EnumClass::CONSTANT->value',
[
'Old\Namespace\OldClass' => [
'enumClass' => 'New\Namespace\EnumClass',
'constants' => [
'OLD_NAME' => 'NEW_NAME',
'SAME_NAME' => 'SAME_NAME',
],
],
]
),
]
);
}

public function configure(array $configuration): void
{
foreach ($configuration as $oldClass => $config) {
$this->transformationMap[$oldClass] = [
'enumClass' => $config['enumClass'],
'constants' => $config['constants'],
];
}
}

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

/**
* @param \PhpParser\Node\Expr\ClassConstFetch $node
*/
public function refactor(Node $node): ?PropertyFetch
{
$className = $this->getName($node->class);
if ($className === null || !isset($this->transformationMap[$className])) {
return null;
}

$constantName = $this->getName($node->name);
if ($constantName === null) {
return null;
}

$transformation = $this->transformationMap[$className];

// Check if this constant is in our mapping
if (!isset($transformation['constants'][$constantName])) {
return null;
}

// Get the mapped constant name (might be the same or different)
$newConstantName = $transformation['constants'][$constantName];

// Create the enum reference: EnumClass::NEW_CONSTANT
$enumRef = new ClassConstFetch(
new FullyQualified($transformation['enumClass']),
$newConstantName
);

// Add the ->value property fetch
return new PropertyFetch($enumRef, 'value');
}
}
34 changes: 34 additions & 0 deletions tests/lib/Rule/ConstToEnumRector/ConstToEnumRectorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Rector\Tests\Rule\ConstToEnumRector;

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

final class ConstToEnumRectorTest extends AbstractRectorTestCase
{
/**
* @throws \Rector\Exception\ShouldNotHappenException
*/
#[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/configured_rule.php';
}
}
45 changes: 45 additions & 0 deletions tests/lib/Rule/ConstToEnumRector/Fixture/some_class.php.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php /** @noinspection ALL */

namespace Ibexa\Rector\Tests\Rule\ConstToEnumValueRector\Fixture;

enum SomeEnum: int
{
case FOO = 1;
case BAZ = 2;
}

class SomeClass
{
public const int FOO = 1;
public const int BAR = 2;

public function someMethod(): int
{
return SomeClass::FOO | SomeClass::BAR;
}
}

?>
-----
<?php /** @noinspection ALL */

namespace Ibexa\Rector\Tests\Rule\ConstToEnumValueRector\Fixture;

enum SomeEnum: int
{
case FOO = 1;
case BAZ = 2;
}

class SomeClass
{
public const int FOO = 1;
public const int BAR = 2;

public function someMethod(): int
{
return \Ibexa\Rector\Tests\Rule\ConstToEnumValueRector\Fixture\EnumClass::FOO->value | \Ibexa\Rector\Tests\Rule\ConstToEnumValueRector\Fixture\EnumClass::BAZ->value;
}
}

?>
25 changes: 25 additions & 0 deletions tests/lib/Rule/ConstToEnumRector/config/configured_rule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

use Ibexa\Rector\Rule\ConstToEnumValueRector;
use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->ruleWithConfiguration(
ConstToEnumValueRector::class,
[
'Ibexa\Rector\Tests\Rule\ConstToEnumValueRector\Fixture\SomeClass' => [
'enumClass' => 'Ibexa\Rector\Tests\Rule\ConstToEnumValueRector\Fixture\EnumClass',
'constants' => [
'FOO' => 'FOO',
'BAR' => 'BAZ',
],
],
]
);
};
32 changes: 32 additions & 0 deletions tests/lib/Sets/Ibexa50/Fixture/rename_relation_const_class.php.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Ibexa\Rector\Tests\Sets\Ibexa50\Fixture;

use Ibexa\Contracts\Core\Repository\Values\Content\Relation;

readonly class Foo
{
public function bar(Relation $relation)
{
$type = Relation::FIELD;
}
}

?>
-----
<?php

namespace Ibexa\Rector\Tests\Sets\Ibexa50\Fixture;

use Ibexa\Contracts\Core\Repository\Values\Content\RelationType;
use Ibexa\Contracts\Core\Repository\Values\Content\Relation;

readonly class Foo
{
public function bar(Relation $relation)
{
$type = RelationType::FIELD->value;
}
}

?>