Skip to content

Commit a419b8f

Browse files
committed
Checking on reserved keywords for class name validity.
1 parent 6624595 commit a419b8f

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

src/Str.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
namespace Symfony\Bundle\MakerBundle;
1313

14-
use Symfony\Component\DependencyInjection\Container;
1514
use Doctrine\Common\Inflector\Inflector;
15+
use Symfony\Component\DependencyInjection\Container;
1616

1717
/**
1818
* @author Javier Eguiluz <[email protected]>
@@ -197,6 +197,29 @@ public static function isValidPhpVariableName($name)
197197
return (bool) preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name, $matches);
198198
}
199199

200+
public static function isValidPhpClassName(string $className): bool
201+
{
202+
$reservedKeywords = ['__halt_compiler', 'abstract', 'and', 'array',
203+
'as', 'break', 'callable', 'case', 'catch', 'class',
204+
'clone', 'const', 'continue', 'declare', 'default', 'die', 'do',
205+
'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor',
206+
'endforeach', 'endif', 'endswitch', 'endwhile', 'eval',
207+
'exit', 'extends', 'final', 'for', 'foreach', 'function',
208+
'global', 'goto', 'if', 'implements', 'include',
209+
'include_once', 'instanceof', 'insteadof', 'interface', 'isset',
210+
'list', 'namespace', 'new', 'or', 'print', 'private',
211+
'protected', 'public', 'require', 'require_once', 'return',
212+
'static', 'switch', 'throw', 'trait', 'try', 'unset',
213+
'use', 'var', 'while', 'xor', '__CLASS__', '__DIR__', '__FILE__',
214+
'__FUNCTION__', '__LINE__', '__METHOD__', '__NAMESPACE__', '__TRAIT__',
215+
'int', 'float', 'bool', 'string', 'true', 'false', 'null', 'void',
216+
'iterable', 'object',
217+
];
218+
219+
return !\in_array(strtolower($className), $reservedKeywords, true) &&
220+
preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $className);
221+
}
222+
200223
public static function areClassesAlphabetical(string $class1, string $class2)
201224
{
202225
$arr1 = [$class1, $class2];

src/Validator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static function validateClassName(string $className, string $errorMessage
2929
$pieces = explode('\\', ltrim($className, '\\'));
3030

3131
foreach ($pieces as $piece) {
32-
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $piece)) {
32+
if (!Str::isValidPhpClassName($piece)) {
3333
$errorMessage = $errorMessage ?: sprintf('"%s" is not valid as a PHP class name (it must start with a letter or underscore, followed by any number of letters, numbers, or underscores)', $className);
3434

3535
throw new RuntimeCommandException($errorMessage);

tests/ValidatorTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,17 @@ public function testInvalidScale()
4949

5050
Validator::validateScale(31);
5151
}
52+
53+
public function testValidateClassName()
54+
{
55+
$this->assertSame('\App\Service\Foo', Validator::validateClassName('\App\Service\Foo'));
56+
$this->assertSame('Foo', Validator::validateClassName('Foo'));
57+
}
58+
59+
public function testInvalidClassName()
60+
{
61+
$this->expectException(RuntimeCommandException::class);
62+
$this->expectExceptionMessage('"class" is not valid as a PHP class name (it must start with a letter or underscore, followed by any number of letters, numbers, or underscores)');
63+
Validator::validateClassName('class');
64+
}
5265
}

0 commit comments

Comments
 (0)