diff --git a/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/Fixture/enum_with_camel_case_names.php.inc b/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/Fixture/enum_with_camel_case_names.php.inc new file mode 100644 index 00000000000..40c5b82381b --- /dev/null +++ b/rules-tests/Php81/Rector/Class_/SpatieEnumClassToEnumRector/Fixture/enum_with_camel_case_names.php.inc @@ -0,0 +1,33 @@ + +----- + diff --git a/rules/Php81/NodeFactory/EnumFactory.php b/rules/Php81/NodeFactory/EnumFactory.php index bbb98194046..be9d9f82f54 100644 --- a/rules/Php81/NodeFactory/EnumFactory.php +++ b/rules/Php81/NodeFactory/EnumFactory.php @@ -4,6 +4,7 @@ namespace Rector\Php81\NodeFactory; +use Nette\Utils\Strings; use PhpParser\BuilderFactory; use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\ArrayItem; @@ -26,6 +27,15 @@ final readonly class EnumFactory { + /** + * @var string + * @see https://stackoverflow.com/a/2560017 + * @see https://regex101.com/r/2xEQVj/1 for changing iso9001 to iso_9001 + * @see https://regex101.com/r/Ykm6ub/1 for changing XMLParser to XML_Parser + * @see https://regex101.com/r/Zv4JhD/1 for changing needsReview to needs_Review + */ + private const PASCAL_CASE_TO_UNDERSCORE_REGEX = '/(?<=[A-Z])(?=[A-Z][a-z])|(?<=[^A-Z])(?=[A-Z])|(?<=[A-Za-z])(?=[^A-Za-z])/'; + public function __construct( private NodeNameResolver $nodeNameResolver, private PhpDocInfoFactory $phpDocInfoFactory, @@ -65,7 +75,7 @@ public function createFromClass(Class_ $class): Enum_ return $enum; } - public function createFromSpatieClass(Class_ $class): Enum_ + public function createFromSpatieClass(Class_ $class, bool $enumNameInSnakeCase = false): Enum_ { $shortClassName = $this->nodeNameResolver->getShortName($class); $enum = new Enum_($shortClassName, [], [ @@ -84,7 +94,12 @@ public function createFromSpatieClass(Class_ $class): Enum_ $enum->scalarType = new Identifier($identifierType); foreach ($docBlockMethods as $docBlockMethod) { - $enum->stmts[] = $this->createEnumCaseFromDocComment($docBlockMethod, $class, $mapping); + $enum->stmts[] = $this->createEnumCaseFromDocComment( + $docBlockMethod, + $class, + $mapping, + $enumNameInSnakeCase + ); } } @@ -117,12 +132,17 @@ private function createEnumCaseFromConst(ClassConst $classConst): EnumCase private function createEnumCaseFromDocComment( PhpDocTagNode $phpDocTagNode, Class_ $class, - array $mapping = [] + array $mapping = [], + bool $enumNameInSnakeCase = false, ): EnumCase { /** @var MethodTagValueNode $nodeValue */ $nodeValue = $phpDocTagNode->value; $enumValue = $mapping[$nodeValue->methodName] ?? $nodeValue->methodName; - $enumName = strtoupper($nodeValue->methodName); + if ($enumNameInSnakeCase) { + $enumName = strtoupper(Strings::replace($nodeValue->methodName, self::PASCAL_CASE_TO_UNDERSCORE_REGEX, '_$0')); + } else { + $enumName = strtoupper($nodeValue->methodName); + } $enumExpr = $this->builderFactory->val($enumValue); return new EnumCase( diff --git a/rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php b/rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php index 56c26c93a51..25f76d540b1 100644 --- a/rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php +++ b/rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php @@ -8,6 +8,7 @@ use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Enum_; use PHPStan\Type\ObjectType; +use Rector\Contract\Rector\ConfigurableRectorInterface; use Rector\Php81\NodeFactory\EnumFactory; use Rector\Rector\AbstractRector; use Rector\ValueObject\PhpVersionFeature; @@ -21,8 +22,10 @@ * * @see \Rector\Tests\Php81\Rector\Class_\SpatieEnumClassToEnumRector\SpatieEnumClassToEnumRectorTest */ -final class SpatieEnumClassToEnumRector extends AbstractRector implements MinPhpVersionInterface +final class SpatieEnumClassToEnumRector extends AbstractRector implements MinPhpVersionInterface, ConfigurableRectorInterface { + private bool $toUpperSnakeCase = false; + public function __construct( private readonly EnumFactory $enumFactory ) { @@ -80,6 +83,14 @@ public function refactor(Node $node): ?Enum_ return null; } - return $this->enumFactory->createFromSpatieClass($node); + return $this->enumFactory->createFromSpatieClass($node, $this->toUpperSnakeCase); + } + + /** + * @param mixed[] $configuration + */ + public function configure(array $configuration): void + { + $this->toUpperSnakeCase = true === ($configuration['toUpperSnakeCase'] ?? false); } }