diff --git a/src/Str.php b/src/Str.php index e2e4f30dd..1e75c222b 100644 --- a/src/Str.php +++ b/src/Str.php @@ -11,8 +11,8 @@ namespace Symfony\Bundle\MakerBundle; -use Symfony\Component\DependencyInjection\Container; use Doctrine\Common\Inflector\Inflector; +use Symfony\Component\DependencyInjection\Container; /** * @author Javier Eguiluz diff --git a/src/Validator.php b/src/Validator.php index 2e1d11b9c..60efdc244 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -27,6 +27,24 @@ public static function validateClassName(string $className, string $errorMessage { // remove potential opening slash so we don't match on it $pieces = explode('\\', ltrim($className, '\\')); + $shortClassName = Str::getShortClassName($className); + + $reservedKeywords = ['__halt_compiler', 'abstract', 'and', 'array', + 'as', 'break', 'callable', 'case', 'catch', 'class', + 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', + 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', + 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', + 'exit', 'extends', 'final', 'for', 'foreach', 'function', + 'global', 'goto', 'if', 'implements', 'include', + 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', + 'list', 'namespace', 'new', 'or', 'print', 'private', + 'protected', 'public', 'require', 'require_once', 'return', + 'static', 'switch', 'throw', 'trait', 'try', 'unset', + 'use', 'var', 'while', 'xor', + 'int', 'float', 'bool', 'string', 'true', 'false', 'null', 'void', + 'iterable', 'object', '__FILE__', '__LINE__', '__DIR__', '__FUNCTION__', '__CLASS__', + '__METHOD__', '__NAMESPACE__', '__TRAIT__', + ]; foreach ($pieces as $piece) { if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $piece)) { @@ -34,6 +52,10 @@ public static function validateClassName(string $className, string $errorMessage throw new RuntimeCommandException($errorMessage); } + + if (\in_array(strtolower($shortClassName), $reservedKeywords, true)) { + throw new RuntimeCommandException(sprintf('"%s" is a reserved keyword and thus cannot be used as class name in PHP.', $shortClassName)); + } } // return original class name diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index ef7df2301..702e445bd 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -49,4 +49,17 @@ public function testInvalidScale() Validator::validateScale(31); } -} \ No newline at end of file + + public function testValidateClassName() + { + $this->assertSame('\App\Service\Foo', Validator::validateClassName('\App\Service\Foo')); + $this->assertSame('Foo', Validator::validateClassName('Foo')); + } + + public function testInvalidClassName() + { + $this->expectException(RuntimeCommandException::class); + $this->expectExceptionMessage('"Class" is a reserved keyword and thus cannot be used as class name in PHP.'); + Validator::validateClassName('App\Entity\Class'); + } +}