From f4d2ede0711a50bcda262e497a9dd849286566eb Mon Sep 17 00:00:00 2001 From: Lonnie Ezell Date: Tue, 26 Dec 2023 22:46:57 -0600 Subject: [PATCH] Test class Generator (#8333) * fixing stuff and replacing files lost in rebase * Fixing namespace test --- phpstan-baseline.php | 425 ------------------ system/CLI/GeneratorTrait.php | 67 +-- system/Commands/Generators/TestGenerator.php | 85 ++++ system/Commands/Generators/Views/test.tpl.php | 18 + system/Config/AutoloadConfig.php | 1 + system/Language/en/CLI.php | 1 + tests/system/Commands/TestGeneratorTest.php | 46 ++ .../Commands/Utilities/NamespacesTest.php | 1 + 8 files changed, 192 insertions(+), 452 deletions(-) create mode 100644 system/Commands/Generators/TestGenerator.php create mode 100644 system/Commands/Generators/Views/test.tpl.php create mode 100644 tests/system/Commands/TestGeneratorTest.php diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 9b87091c6800..50a0f6c5eef5 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -201,431 +201,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/Commands/Encryption/GenerateKey.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/CellGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\CellGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CellGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\CellGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CellGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CellGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CellGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CellGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/CellGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/CommandGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\CommandGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CommandGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\CommandGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CommandGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CommandGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CommandGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/CommandGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/CommandGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ConfigGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ConfigGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ConfigGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ConfigGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ConfigGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ConfigGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ConfigGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ConfigGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ConfigGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ControllerGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ControllerGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in an elseif condition, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in an if condition, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in \\|\\|, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in \\|\\|, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ControllerGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/EntityGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\EntityGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/EntityGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\EntityGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/EntityGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/EntityGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/EntityGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/EntityGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/EntityGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/FilterGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\FilterGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/FilterGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\FilterGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/FilterGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/FilterGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/FilterGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/FilterGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/FilterGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/MigrationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\MigrationGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/MigrationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\MigrationGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/MigrationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/MigrationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/MigrationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/MigrationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in an if condition, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/MigrationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/MigrationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ModelGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ModelGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ModelGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ModelGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ModelGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ModelGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ModelGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ModelGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in an if condition, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ModelGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ModelGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ScaffoldGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ScaffoldGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ScaffoldGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ScaffoldGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ScaffoldGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ScaffoldGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ScaffoldGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ScaffoldGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in an elseif condition, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ScaffoldGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in an if condition, mixed given\\.$#', - 'count' => 4, - 'path' => __DIR__ . '/system/Commands/Generators/ScaffoldGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ScaffoldGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/SeederGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\SeederGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/SeederGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\SeederGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/SeederGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/SeederGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/SeederGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/SeederGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/SeederGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ValidationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ValidationGenerator\\:\\:generateClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ValidationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Generators\\\\ValidationGenerator\\:\\:generateView\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ValidationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the left side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ValidationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in &&, mixed given on the right side\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ValidationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a negated boolean, mixed given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Commands/Generators/ValidationGenerator.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/Commands/Generators/ValidationGenerator.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Commands\\\\ListCommands\\:\\:listFull\\(\\) has no return type specified\\.$#', 'count' => 1, diff --git a/system/CLI/GeneratorTrait.php b/system/CLI/GeneratorTrait.php index 349cccb2da63..d82bd05dc7e2 100644 --- a/system/CLI/GeneratorTrait.php +++ b/system/CLI/GeneratorTrait.php @@ -59,6 +59,12 @@ trait GeneratorTrait */ protected $classNameLang = ''; + /** + * Namespace to use for class. + * Leave null to use the default namespace. + */ + protected ?string $namespace = null; + /** * Whether to require class name. * @@ -108,7 +114,7 @@ protected function execute(array $params): void /** * Generates a class file from an existing template. */ - protected function generateClass(array $params) + protected function generateClass(array $params): void { $this->params = $params; @@ -119,7 +125,7 @@ protected function generateClass(array $params) $target = $this->buildPath($class); // Check if path is empty. - if (empty($target)) { + if ($target === '') { return; } @@ -131,14 +137,14 @@ protected function generateClass(array $params) * * @param string $view namespaced view name that is generated */ - protected function generateView(string $view, array $params) + protected function generateView(string $view, array $params): void { $this->params = $params; $target = $this->buildPath($view); // Check if path is empty. - if (empty($target)) { + if ($target === '') { return; } @@ -263,8 +269,10 @@ protected function qualifyClassName(): string if ($class === null && $this->hasClassName) { // @codeCoverageIgnoreStart - $nameLang = $this->classNameLang ?: 'CLI.generator.className.default'; - $class = CLI::prompt(lang($nameLang), null, 'required'); + $nameLang = $this->classNameLang !== '' + ? $this->classNameLang + : 'CLI.generator.className.default'; + $class = CLI::prompt(lang($nameLang), null, 'required'); CLI::newLine(); // @codeCoverageIgnoreEnd } @@ -302,20 +310,15 @@ protected function qualifyClassName(): string ); // Gets the namespace from input. Don't forget the ending backslash! - $namespace = trim( - str_replace( - '/', - '\\', - $this->getOption('namespace') ?? APP_NAMESPACE - ), - '\\' - ) . '\\'; + $namespace = $this->getNamespace() . '\\'; if (strncmp($class, $namespace, strlen($namespace)) === 0) { return $class; // @codeCoverageIgnore } - return $namespace . $this->directory . '\\' . str_replace('/', '\\', $class); + $directoryString = ($this->directory !== null) ? $this->directory . '\\' : ''; + + return $namespace . $directoryString . str_replace('/', '\\', $class); } /** @@ -403,14 +406,7 @@ protected function buildContent(string $class): string */ protected function buildPath(string $class): string { - $namespace = trim( - str_replace( - '/', - '\\', - $this->getOption('namespace') ?? APP_NAMESPACE - ), - '\\' - ); + $namespace = $this->getNamespace(); // Check if the namespace is actually defined and we are not just typing gibberish. $base = Services::autoloader()->getNamespace($namespace); @@ -426,7 +422,9 @@ protected function buildPath(string $class): string return ''; } - $base = realpath($base) ?: $base; + $realpath = realpath($base); + $base = ($realpath !== false) ? $realpath : $base; + $file = $base . DIRECTORY_SEPARATOR . str_replace( '\\', @@ -444,6 +442,23 @@ protected function buildPath(string $class): string ) . DIRECTORY_SEPARATOR . $this->basename($file); } + /** + * Gets the namespace from the command-line option, + * or the default namespace if the option is not set. + * Can be overridden by directly setting $this->namespace. + */ + protected function getNamespace(): string + { + return $this->namespace ?? trim( + str_replace( + '/', + '\\', + $this->getOption('namespace') ?? APP_NAMESPACE + ), + '\\' + ); + } + /** * Allows child generators to modify the internal `$hasClassName` flag. * @@ -483,10 +498,8 @@ protected function setEnabledSuffixing(bool $enabledSuffixing) /** * Gets a single command-line option. Returns TRUE if the option exists, * but doesn't have a value, and is simply acting as a flag. - * - * @return mixed */ - protected function getOption(string $name) + protected function getOption(string $name): string|bool|null { if (! array_key_exists($name, $this->params)) { return CLI::getOption($name); diff --git a/system/Commands/Generators/TestGenerator.php b/system/Commands/Generators/TestGenerator.php new file mode 100644 index 000000000000..33f006604e8d --- /dev/null +++ b/system/Commands/Generators/TestGenerator.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Commands\Generators; + +use CodeIgniter\CLI\BaseCommand; +use CodeIgniter\CLI\GeneratorTrait; + +/** + * Generates a skeleton command file. + */ +class TestGenerator extends BaseCommand +{ + use GeneratorTrait; + + /** + * The Command's Group + * + * @var string + */ + protected $group = 'Generators'; + + /** + * The Command's Name + * + * @var string + */ + protected $name = 'make:test'; + + /** + * The Command's Description + * + * @var string + */ + protected $description = 'Generates a new test file.'; + + /** + * The Command's Usage + * + * @var string + */ + protected $usage = 'make:test [options]'; + + /** + * The Command's Arguments + * + * @var array + */ + protected $arguments = [ + 'name' => 'The command class name.', + ]; + + /** + * The Command's Options + * + * @var array + */ + protected $options = [ + '--namespace' => 'Set root namespace. Default: "APP_NAMESPACE".', + '--force' => 'Force overwrite existing file.', + ]; + + /** + * Actually execute a command. + */ + public function run(array $params) + { + $this->component = 'Test'; + $this->template = 'test.tpl.php'; + $this->namespace = 'Tests'; + + $this->classNameLang = 'CLI.generator.className.test'; + $this->generateClass($params); + } +} diff --git a/system/Commands/Generators/Views/test.tpl.php b/system/Commands/Generators/Views/test.tpl.php new file mode 100644 index 000000000000..f67348d079f8 --- /dev/null +++ b/system/Commands/Generators/Views/test.tpl.php @@ -0,0 +1,18 @@ +<@php + +namespace {namespace}; + +use CodeIgniter\Test\CIUnitTestCase; + +class {class} extends CIUnitTestCase +{ + protected function setUp(): void + { + parent::setUp(); + } + + public function testExample(): void + { + // + } +} diff --git a/system/Config/AutoloadConfig.php b/system/Config/AutoloadConfig.php index d5f515ecdf81..f70d07155613 100644 --- a/system/Config/AutoloadConfig.php +++ b/system/Config/AutoloadConfig.php @@ -93,6 +93,7 @@ class AutoloadConfig protected $corePsr4 = [ 'CodeIgniter' => SYSTEMPATH, 'Config' => APPPATH . 'Config', + 'Tests' => ROOTPATH . 'tests', ]; /** diff --git a/system/Language/en/CLI.php b/system/Language/en/CLI.php index 16f34482c711..f636fb2131d4 100644 --- a/system/Language/en/CLI.php +++ b/system/Language/en/CLI.php @@ -29,6 +29,7 @@ 'migration' => 'Migration class name', 'model' => 'Model class name', 'seeder' => 'Seeder class name', + 'test' => 'Test class name', 'validation' => 'Validation class name', ], 'commandType' => 'Command type', diff --git a/tests/system/Commands/TestGeneratorTest.php b/tests/system/Commands/TestGeneratorTest.php new file mode 100644 index 000000000000..8ffe89c3de55 --- /dev/null +++ b/tests/system/Commands/TestGeneratorTest.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Commands; + +use CodeIgniter\Test\CIUnitTestCase; +use CodeIgniter\Test\StreamFilterTrait; + +/** + * @internal + * + * @group Others + */ +final class TestGeneratorTest extends CIUnitTestCase +{ + use StreamFilterTrait; + + protected function tearDown(): void + { + $result = str_replace(["\033[0;32m", "\033[0m", "\n"], '', $this->getStreamFilterBuffer()); + $file = str_replace('ROOTPATH' . DIRECTORY_SEPARATOR, ROOTPATH, trim(substr($result, 14))); + $dir = dirname($file); + if (is_file($file)) { + unlink($file); + } + if (is_dir($dir)) { + rmdir($dir); + } + } + + public function testGenerateTest(): void + { + command('make:test Foo/Bar'); + $this->assertFileExists(ROOTPATH . 'tests/Foo/Bar.php'); + } +} diff --git a/tests/system/Commands/Utilities/NamespacesTest.php b/tests/system/Commands/Utilities/NamespacesTest.php index fae294afb2ff..809a3a64d29d 100644 --- a/tests/system/Commands/Utilities/NamespacesTest.php +++ b/tests/system/Commands/Utilities/NamespacesTest.php @@ -59,6 +59,7 @@ public function testNamespacesCommandCodeIgniterOnly(): void +---------------+-------------------------+--------+ | CodeIgniter | ROOTPATH/system | Yes | | Config | APPPATH/Config | Yes | + | Tests | ROOTPATH/tests | Yes | | App | ROOTPATH/app | Yes | | Tests\Support | ROOTPATH/tests/_support | Yes | +---------------+-------------------------+--------+