Skip to content
Open
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
4 changes: 2 additions & 2 deletions system/CLI/AbstractGeneratorCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ protected function configure(): void

protected function provideDefaultOptions(): void
{
parent::provideDefaultOptions();

$this->provideGeneratorOptions();

parent::provideDefaultOptions();
}

/**
Expand Down
173 changes: 75 additions & 98 deletions system/Commands/Generators/ControllerGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,126 +13,103 @@

namespace CodeIgniter\Commands\Generators;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\AbstractGeneratorCommand;
use CodeIgniter\CLI\Attributes\Command;
use CodeIgniter\CLI\Attributes\GeneratorCommand;
use CodeIgniter\CLI\CLI;
use CodeIgniter\CLI\GeneratorTrait;
use CodeIgniter\CLI\Input\Option;
use CodeIgniter\Controller;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\RESTful\ResourcePresenter;

/**
* Generates a skeleton controller file.
*/
class ControllerGenerator extends BaseCommand
#[Command(name: 'make:controller', description: 'Generates a new controller file.', group: 'Generators')]
#[GeneratorCommand(
component: 'Controller',
template: 'controller.tpl.php',
directory: 'Controllers',
classNameLang: 'CLI.generator.className.controller',
)]
class ControllerGenerator extends AbstractGeneratorCommand
{
use GeneratorTrait;
protected function configure(): void
{
parent::configure();

$this
->addOption(new Option(
name: 'bare',
shortcut: 'b',
description: 'Extend CodeIgniter\Controller instead of BaseController.',
))
->addOption(new Option(
name: 'restful',
shortcut: 'r',
description: 'Extend a RESTful resource: "controller" (default when no value is given) or "presenter".',
acceptsValue: true,
valueLabel: 'type',
));
}

/**
* The Command's Group
*
* @var string
*/
protected $group = 'Generators';
protected function interact(array &$arguments, array &$options): void
{
$type = $this->getUnboundOption('restful', $options);

/**
* The Command's Name
*
* @var string
*/
protected $name = 'make:controller';
if (! is_string($type) || $type === 'controller' || $type === 'presenter') {
return;
}

/**
* The Command's Description
*
* @var string
*/
protected $description = 'Generates a new controller file.';
$options['restful'] = CLI::prompt(lang('CLI.generator.parentClass'), ['controller', 'presenter'], 'required');
}

/**
* The Command's Usage
*
* @var string
*/
protected $usage = 'make:controller <name> [options]';
protected function execute(array $arguments, array $options): int
{
$type = $this->getResourceType();

/**
* The Command's Arguments
*
* @var array<string, string>
*/
protected $arguments = [
'name' => 'The controller class name.',
];
if (! in_array($type, [null, 'controller', 'presenter'], true)) {
CLI::error(lang('CLI.generator.invalidParentClass', [$type]));

/**
* The Command's Options
*
* @var array<string, string>
*/
protected $options = [
'--bare' => 'Extends from CodeIgniter\Controller instead of BaseController.',
'--restful' => 'Extends from a RESTful resource, Options: [controller, presenter]. Default: "controller".',
'--namespace' => 'Set root namespace. Default: "APP_NAMESPACE".',
'--suffix' => 'Append the component title to the class name (e.g. User => UserController).',
'--force' => 'Force overwrite existing file.',
];
return EXIT_ERROR;
}

/**
* Actually execute a command.
*/
public function run(array $params)
return $this->generateClass();
}

protected function getReplacements(string $class): array
{
$this->component = 'Controller';
$this->directory = 'Controllers';
$this->template = 'controller.tpl.php';
$parent = $this->getParentClass();

$this->classNameLang = 'CLI.generator.className.controller';
$this->generateClass($params);
return ['{useStatement}' => $parent, '{extends}' => class_basename($parent)];
}

protected function getTemplateData(string $class): array
{
return ['type' => $this->getValidatedOption('bare') === true ? null : $this->getResourceType()];
}

return EXIT_SUCCESS;
private function getParentClass(): string
{
if ($this->getValidatedOption('bare') === true) {
return Controller::class;
}

return match ($this->getResourceType()) {
'controller' => ResourceController::class,
'presenter' => ResourcePresenter::class,
default => trim(APP_NAMESPACE, '\\') . '\\Controllers\\BaseController',
};
}

/**
* Prepare options and do the necessary replacements.
* Returns the RESTful resource type, or `null` when `--restful` was not passed.
*/
protected function prepare(string $class): string
private function getResourceType(): ?string
{
$bare = $this->getOption('bare');
$rest = $this->getOption('restful');

$useStatement = trim(APP_NAMESPACE, '\\') . '\Controllers\BaseController';
$extends = 'BaseController';

// Gets the appropriate parent class to extend.
if ($bare || $rest) {
if ($bare) {
$useStatement = Controller::class;
$extends = 'Controller';
} elseif ($rest) {
$rest = is_string($rest) ? $rest : 'controller';

if (! in_array($rest, ['controller', 'presenter'], true)) {
// @codeCoverageIgnoreStart
$rest = CLI::prompt(lang('CLI.generator.parentClass'), ['controller', 'presenter'], 'required');
CLI::newLine();
// @codeCoverageIgnoreEnd
}

if ($rest === 'controller') {
$useStatement = ResourceController::class;
$extends = 'ResourceController';
} elseif ($rest === 'presenter') {
$useStatement = ResourcePresenter::class;
$extends = 'ResourcePresenter';
}
}
if (! $this->hasUnboundOption('restful')) {
return null;
}

return $this->parseTemplate(
$class,
['{useStatement}', '{extends}'],
[$useStatement, $extends],
['type' => $rest],
);
$type = $this->getValidatedOption('restful');

return is_string($type) ? $type : 'controller';
}
}
4 changes: 3 additions & 1 deletion system/Commands/Generators/ScaffoldGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ public function run(array $params)
if ($this->getOption('bare')) {
$controllerOpts['bare'] = null;
} elseif ($this->getOption('restful')) {
$controllerOpts['restful'] = $this->getOption('restful');
$restful = $this->getOption('restful');

$controllerOpts['restful'] = is_string($restful) ? $restful : null;
}

$modelOpts = [
Expand Down
27 changes: 14 additions & 13 deletions system/Language/en/CLI.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,20 @@
'transformer' => 'Transformer class name',
'validation' => 'Validation class name',
],
'commandType' => 'Command type',
'confirmContinue' => 'Are you sure you want to continue?',
'databaseGroup' => 'Database group',
'fileCreate' => 'File created: {0}',
'fileError' => 'Error while creating file: "{0}"',
'fileExist' => 'File exists: "{0}"',
'fileOverwrite' => 'File overwritten: "{0}"',
'invalidClassName' => 'Class name "{0}" is not valid.',
'parentClass' => 'Parent class',
'returnType' => 'Return type',
'tableName' => 'Table name',
'usingCINamespace' => 'Warning: Using the "CodeIgniter" namespace will generate the file in the system directory.',
'viewName' => [
'commandType' => 'Command type',
'confirmContinue' => 'Are you sure you want to continue?',
'databaseGroup' => 'Database group',
'fileCreate' => 'File created: {0}',
'fileError' => 'Error while creating file: "{0}"',
'fileExist' => 'File exists: "{0}"',
'fileOverwrite' => 'File overwritten: "{0}"',
'invalidClassName' => 'Class name "{0}" is not valid.',
'invalidParentClass' => 'Parent class "{0}" is not valid.',
'parentClass' => 'Parent class',
'returnType' => 'Return type',
'tableName' => 'Table name',
'usingCINamespace' => 'Warning: Using the "CodeIgniter" namespace will generate the file in the system directory.',
'viewName' => [
'cell' => 'Cell view name',
],
],
Expand Down
6 changes: 3 additions & 3 deletions tests/system/CLI/AbstractGeneratorCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ public function testCommandDeclaresGeneratorDefinition(): void
$this->assertSame(['name'], array_keys($arguments));
$this->assertTrue($arguments['name']->required);
$this->assertSame(
['help', 'no-header', 'no-interaction', 'namespace', 'suffix', 'force'],
['namespace', 'suffix', 'force', 'help', 'no-header', 'no-interaction'],
array_keys($command->getOptionsDefinition()),
);
$this->assertSame(
['h' => 'help', 'N' => 'no-interaction', 'n' => 'namespace', 's' => 'suffix', 'f' => 'force'],
['n' => 'namespace', 's' => 'suffix', 'f' => 'force', 'h' => 'help', 'N' => 'no-interaction'],
$command->getShortcuts(),
);
$this->assertSame('make:testwidget [options] [--] <name>', $command->getUsages()[0]);
Expand All @@ -99,7 +99,7 @@ public function testTrimmedCommandDeclaresReducedDefinition(): void
$command = new TrimmedOptionsGeneratorCommand(new Commands());

$this->assertSame(
['help', 'no-header', 'no-interaction', 'namespace'],
['namespace', 'help', 'no-header', 'no-interaction'],
array_keys($command->getOptionsDefinition()),
);
}
Expand Down
Loading
Loading