Skip to content

Commit

Permalink
Merge pull request #8119 from kenjis/feat-generator-multiple-views
Browse files Browse the repository at this point in the history
feat: one generator command could have multiple views
  • Loading branch information
kenjis authored Nov 3, 2023
2 parents ea357ba + 2534fdc commit d4388f0
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 36 deletions.
8 changes: 5 additions & 3 deletions app/Config/Generators.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ class Generators extends BaseConfig
*
* YOU HAVE BEEN WARNED!
*
* @var array<string, string>
* @var array<string, array<string, string>|string>
*/
public array $views = [
'make:cell' => 'CodeIgniter\Commands\Generators\Views\cell.tpl.php',
'make:cell_view' => 'CodeIgniter\Commands\Generators\Views\cell_view.tpl.php',
'make:cell' => [
'class' => 'CodeIgniter\Commands\Generators\Views\cell.tpl.php',
'view' => 'CodeIgniter\Commands\Generators\Views\cell_view.tpl.php',
],
'make:command' => 'CodeIgniter\Commands\Generators\Views\command.tpl.php',
'make:config' => 'CodeIgniter\Commands\Generators\Views\config.tpl.php',
'make:controller' => 'CodeIgniter\Commands\Generators\Views\controller.tpl.php',
Expand Down
147 changes: 127 additions & 20 deletions system/CLI/GeneratorTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,15 @@ trait GeneratorTrait
protected $directory;

/**
* View template name
* (Optional) View template path
*
* We use special namespaced paths like:
* `CodeIgniter\Commands\Generators\Views\cell.tpl.php`.
*/
protected ?string $templatePath = null;

/**
* View template name for fallback
*
* @var string
*/
Expand Down Expand Up @@ -118,6 +126,8 @@ protected function generateClass(array $params)

/**
* Generate a view file from an existing template.
*
* @param string $view namespaced view name that is generated
*/
protected function generateView(string $view, array $params)
{
Expand All @@ -135,6 +145,8 @@ protected function generateView(string $view, array $params)

/**
* Handles writing the file to disk, and all of the safety checks around that.
*
* @param string $target file path
*/
private function generateFile(string $target, string $content): void
{
Expand All @@ -143,7 +155,13 @@ private function generateFile(string $target, string $content): void
CLI::write(lang('CLI.generator.usingCINamespace'), 'yellow');
CLI::newLine();

if (CLI::prompt('Are you sure you want to continue?', ['y', 'n'], 'required') === 'n') {
if (
CLI::prompt(
'Are you sure you want to continue?',
['y', 'n'],
'required'
) === 'n'
) {
CLI::newLine();
CLI::write(lang('CLI.generator.cancelOperation'), 'yellow');
CLI::newLine();
Expand All @@ -160,7 +178,11 @@ private function generateFile(string $target, string $content): void
// Overwriting files unknowingly is a serious annoyance, So we'll check if
// we are duplicating things, If 'force' option is not supplied, we bail.
if (! $this->getOption('force') && $isFile) {
CLI::error(lang('CLI.generator.fileExist', [clean_path($target)]), 'light_gray', 'red');
CLI::error(
lang('CLI.generator.fileExist', [clean_path($target)]),
'light_gray',
'red'
);
CLI::newLine();

return;
Expand All @@ -179,26 +201,40 @@ private function generateFile(string $target, string $content): void
// contents from the template, and then we'll do the necessary replacements.
if (! write_file($target, $content)) {
// @codeCoverageIgnoreStart
CLI::error(lang('CLI.generator.fileError', [clean_path($target)]), 'light_gray', 'red');
CLI::error(
lang('CLI.generator.fileError', [clean_path($target)]),
'light_gray',
'red'
);
CLI::newLine();

return;
// @codeCoverageIgnoreEnd
}

if ($this->getOption('force') && $isFile) {
CLI::write(lang('CLI.generator.fileOverwrite', [clean_path($target)]), 'yellow');
CLI::write(
lang('CLI.generator.fileOverwrite', [clean_path($target)]),
'yellow'
);
CLI::newLine();

return;
}

CLI::write(lang('CLI.generator.fileCreate', [clean_path($target)]), 'green');
CLI::write(
lang('CLI.generator.fileCreate', [clean_path($target)]),
'green'
);
CLI::newLine();
}

/**
* Prepare options and do the necessary replacements.
*
* @param string $class namespaced classname or namespaced view.
*
* @return string generated file content
*/
protected function prepare(string $class): string
{
Expand Down Expand Up @@ -244,15 +280,34 @@ protected function qualifyClassName(): string
$class = $matches[1] . ucfirst($matches[2]);
}

if ($this->enabledSuffixing && $this->getOption('suffix') && preg_match($pattern, $class) !== 1) {
if (
$this->enabledSuffixing && $this->getOption('suffix')
&& preg_match($pattern, $class) !== 1
) {
$class .= ucfirst($component);
}

// Trims input, normalize separators, and ensure that all paths are in Pascalcase.
$class = ltrim(implode('\\', array_map('pascalize', explode('\\', str_replace('/', '\\', trim($class))))), '\\/');
$class = ltrim(
implode(
'\\',
array_map(
'pascalize',
explode('\\', str_replace('/', '\\', trim($class)))
)
),
'\\/'
);

// Gets the namespace from input. Don't forget the ending backslash!
$namespace = trim(str_replace('/', '\\', $this->getOption('namespace') ?? APP_NAMESPACE), '\\') . '\\';
$namespace = trim(
str_replace(
'/',
'\\',
$this->getOption('namespace') ?? APP_NAMESPACE
),
'\\'
) . '\\';

if (strncmp($class, $namespace, strlen($namespace)) === 0) {
return $class; // @codeCoverageIgnore
Expand All @@ -268,21 +323,41 @@ protected function qualifyClassName(): string
protected function renderTemplate(array $data = []): string
{
try {
return view(config(Generators::class)->views[$this->name], $data, ['debug' => false]);
$template = $this->templatePath ?? config(Generators::class)->views[$this->name];

return view($template, $data, ['debug' => false]);
} catch (Throwable $e) {
log_message('error', (string) $e);

return view("CodeIgniter\\Commands\\Generators\\Views\\{$this->template}", $data, ['debug' => false]);
return view(
"CodeIgniter\\Commands\\Generators\\Views\\{$this->template}",
$data,
['debug' => false]
);
}
}

/**
* Performs pseudo-variables contained within view file.
*
* @param string $class namespaced classname or namespaced view.
*
* @return string generated file content
*/
protected function parseTemplate(string $class, array $search = [], array $replace = [], array $data = []): string
{
protected function parseTemplate(
string $class,
array $search = [],
array $replace = [],
array $data = []
): string {
// Retrieves the namespace part from the fully qualified class name.
$namespace = trim(implode('\\', array_slice(explode('\\', $class), 0, -1)), '\\');
$namespace = trim(
implode(
'\\',
array_slice(explode('\\', $class), 0, -1)
),
'\\'
);
$search[] = '<@php';
$search[] = '{namespace}';
$search[] = '{class}';
Expand All @@ -302,7 +377,14 @@ protected function buildContent(string $class): string
{
$template = $this->prepare($class);

if ($this->sortImports && preg_match('/(?P<imports>(?:^use [^;]+;$\n?)+)/m', $template, $match)) {
if (
$this->sortImports
&& preg_match(
'/(?P<imports>(?:^use [^;]+;$\n?)+)/m',
$template,
$match
)
) {
$imports = explode("\n", trim($match['imports']));
sort($imports);

Expand All @@ -314,25 +396,50 @@ protected function buildContent(string $class): string

/**
* Builds the file path from the class name.
*
* @param string $class namespaced classname or namespaced view.
*/
protected function buildPath(string $class): string
{
$namespace = trim(str_replace('/', '\\', $this->getOption('namespace') ?? APP_NAMESPACE), '\\');
$namespace = trim(
str_replace(
'/',
'\\',
$this->getOption('namespace') ?? APP_NAMESPACE
),
'\\'
);

// Check if the namespace is actually defined and we are not just typing gibberish.
$base = Services::autoloader()->getNamespace($namespace);

if (! $base = reset($base)) {
CLI::error(lang('CLI.namespaceNotDefined', [$namespace]), 'light_gray', 'red');
CLI::error(
lang('CLI.namespaceNotDefined', [$namespace]),
'light_gray',
'red'
);
CLI::newLine();

return '';
}

$base = realpath($base) ?: $base;
$file = $base . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, trim(str_replace($namespace . '\\', '', $class), '\\')) . '.php';

return implode(DIRECTORY_SEPARATOR, array_slice(explode(DIRECTORY_SEPARATOR, $file), 0, -1)) . DIRECTORY_SEPARATOR . $this->basename($file);
$file = $base . DIRECTORY_SEPARATOR
. str_replace(
'\\',
DIRECTORY_SEPARATOR,
trim(str_replace($namespace . '\\', '', $class), '\\')
) . '.php';

return implode(
DIRECTORY_SEPARATOR,
array_slice(
explode(DIRECTORY_SEPARATOR, $file),
0,
-1
)
) . DIRECTORY_SEPARATOR . $this->basename($file);
}

/**
Expand Down
11 changes: 9 additions & 2 deletions system/Commands/Generators/CellGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\GeneratorTrait;
use Config\Generators;

/**
* Generates a skeleton Cell and its view.
Expand Down Expand Up @@ -78,17 +79,23 @@ public function run(array $params)

$params = array_merge($params, ['suffix' => null]);

$this->templatePath = config(Generators::class)->views[$this->name]['class'];
$this->template = 'cell.tpl.php';
$this->classNameLang = 'CLI.generator.className.cell';

$this->generateClass($params);

$this->name = 'make:cell_view';
$this->templatePath = config(Generators::class)->views[$this->name]['view'];
$this->template = 'cell_view.tpl.php';
$this->classNameLang = 'CLI.generator.viewName.cell';

$className = $this->qualifyClassName();
$viewName = decamelize(class_basename($className));
$viewName = preg_replace('/([a-z][a-z0-9_\/\\\\]+)(_cell)$/i', '$1', $viewName) ?? $viewName;
$viewName = preg_replace(
'/([a-z][a-z0-9_\/\\\\]+)(_cell)$/i',
'$1',
$viewName
) ?? $viewName;
$namespace = substr($className, 0, strrpos($className, '\\') + 1);

$this->generateView($namespace . $viewName, $params);
Expand Down
2 changes: 1 addition & 1 deletion system/Commands/Generators/CommandGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function run(array $params)
$this->template = 'command.tpl.php';

$this->classNameLang = 'CLI.generator.className.command';
$this->execute($params);
$this->generateClass($params);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion system/Commands/Generators/ConfigGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public function run(array $params)
$this->template = 'config.tpl.php';

$this->classNameLang = 'CLI.generator.className.config';
$this->execute($params);
$this->generateClass($params);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion system/Commands/Generators/ControllerGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function run(array $params)
$this->template = 'controller.tpl.php';

$this->classNameLang = 'CLI.generator.className.controller';
$this->execute($params);
$this->generateClass($params);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion system/Commands/Generators/EntityGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ public function run(array $params)
$this->template = 'entity.tpl.php';

$this->classNameLang = 'CLI.generator.className.entity';
$this->execute($params);
$this->generateClass($params);
}
}
2 changes: 1 addition & 1 deletion system/Commands/Generators/FilterGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ public function run(array $params)
$this->template = 'filter.tpl.php';

$this->classNameLang = 'CLI.generator.className.filter';
$this->execute($params);
$this->generateClass($params);
}
}
2 changes: 1 addition & 1 deletion system/Commands/Generators/MigrationGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function run(array $params)
}

$this->classNameLang = 'CLI.generator.className.migration';
$this->execute($params);
$this->generateClass($params);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion system/Commands/Generators/ModelGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function run(array $params)
$this->template = 'model.tpl.php';

$this->classNameLang = 'CLI.generator.className.model';
$this->execute($params);
$this->generateClass($params);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion system/Commands/Generators/SeederGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ public function run(array $params)
$this->template = 'seeder.tpl.php';

$this->classNameLang = 'CLI.generator.className.seeder';
$this->execute($params);
$this->generateClass($params);
}
}
2 changes: 1 addition & 1 deletion system/Commands/Generators/ValidationGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ public function run(array $params)
$this->template = 'validation.tpl.php';

$this->classNameLang = 'CLI.generator.className.validation';
$this->execute($params);
$this->generateClass($params);
}
}
Loading

0 comments on commit d4388f0

Please sign in to comment.