From f93a0d4f0c355ade9ca2fa677e23cd4a37c637dd Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Thu, 13 Aug 2026 19:59:59 +0800 Subject: [PATCH] refactor: migrate `namespaces` command as modern command --- system/Commands/Utilities/Namespaces.php | 164 ++++++------------ .../Commands/Utilities/NamespacesTest.php | 2 +- user_guide_src/source/changelogs/v4.8.0.rst | 1 + utils/phpstan-baseline/loader.neon | 2 +- .../missingType.iterableValue.neon | 22 +-- 5 files changed, 56 insertions(+), 135 deletions(-) diff --git a/system/Commands/Utilities/Namespaces.php b/system/Commands/Utilities/Namespaces.php index bee2486c31b8..2b0965ab54f6 100644 --- a/system/Commands/Utilities/Namespaces.php +++ b/system/Commands/Utilities/Namespaces.php @@ -13,105 +13,77 @@ namespace CodeIgniter\Commands\Utilities; -use CodeIgniter\CLI\BaseCommand; +use CodeIgniter\CLI\AbstractCommand; +use CodeIgniter\CLI\Attributes\Command; use CodeIgniter\CLI\CLI; +use CodeIgniter\CLI\Input\Option; use Config\Autoload; /** - * Lists namespaces set in Config\Autoload with their - * full server path. Helps you to verify that you have - * the namespaces setup correctly. + * Lists namespaces set in Config\Autoload with their full server path. * * @see \CodeIgniter\Commands\Utilities\NamespacesTest */ -class Namespaces extends BaseCommand +#[Command( + name: 'namespaces', + description: 'Verifies your namespaces are setup correctly.', + group: 'CodeIgniter', +)] +class Namespaces extends AbstractCommand { - /** - * The group the command is lumped under - * when listing commands. - * - * @var string - */ - protected $group = 'CodeIgniter'; - - /** - * The Command's name - * - * @var string - */ - protected $name = 'namespaces'; - - /** - * the Command's short description - * - * @var string - */ - protected $description = 'Verifies your namespaces are setup correctly.'; - - /** - * the Command's usage - * - * @var string - */ - protected $usage = 'namespaces'; - - /** - * the Command's Arguments - * - * @var array - */ - protected $arguments = []; - - /** - * the Command's Options - * - * @var array - */ - protected $options = [ - '-c' => 'Show only CodeIgniter config namespaces.', - '-r' => 'Show raw path strings.', - '-m' => 'Specify max length of the path strings to output. Default: 60.', - ]; - - /** - * Displays the help for the spark cli script itself. - */ - public function run(array $params) + protected function configure(): void { - $params['m'] = (int) ($params['m'] ?? 60); + $this + ->addOption(new Option( + name: 'config-only', + shortcut: 'c', + description: 'Show only CodeIgniter config namespaces.', + )) + ->addOption(new Option( + name: 'raw', + shortcut: 'r', + description: 'Show raw path strings.', + )) + ->addOption(new Option( + name: 'max-length', + shortcut: 'm', + description: 'Specify max length of the path strings to output.', + requiresValue: true, + default: '60', + )); + } - $tbody = array_key_exists('c', $params) ? $this->outputCINamespaces($params) : $this->outputAllNamespaces($params); + protected function execute(array $arguments, array $options): int + { + $namespaces = $options['config-only'] !== false + ? (new Autoload())->psr4 + : service('autoloader')->getNamespace(); - $thead = [ - 'Namespace', - 'Path', - 'Found?', - ]; + $tbody = $this->buildTable( + $namespaces, + $options['raw'] !== false, + (int) $options['max-length'], + ); - CLI::table($tbody, $thead); + CLI::table($tbody, ['Namespace', 'Path', 'Found?']); return EXIT_SUCCESS; } - private function outputAllNamespaces(array $params): array + /** + * @param array|string> $namespaces + * + * @return list> + */ + private function buildTable(array $namespaces, bool $raw, int $maxLength): array { - $maxLength = $params['m']; - - $autoloader = service('autoloader'); - $tbody = []; - foreach ($autoloader->getNamespace() as $ns => $paths) { - foreach ($paths as $path) { - if (array_key_exists('r', $params)) { - $pathOutput = $this->truncate($path, $maxLength); - } else { - $pathOutput = $this->truncate(clean_path($path), $maxLength); - } - + foreach ($namespaces as $namespace => $paths) { + foreach ((array) $paths as $path) { $tbody[] = [ - $ns, - $pathOutput, + $namespace, + $this->truncate($raw ? $path : clean_path($path), $maxLength), is_dir($path) ? 'Yes' : 'MISSING', ]; } @@ -122,42 +94,10 @@ private function outputAllNamespaces(array $params): array private function truncate(string $string, int $max): string { - $length = mb_strlen($string); - - if ($length > $max) { + if (mb_strlen($string) > $max) { return mb_substr($string, 0, $max - 3) . '...'; } return $string; } - - private function outputCINamespaces(array $params): array - { - $maxLength = $params['m']; - - $config = new Autoload(); - - $tbody = []; - - foreach ($config->psr4 as $ns => $paths) { - foreach ((array) $paths as $path) { - if (array_key_exists('r', $params)) { - $pathOutput = $this->truncate($path, $maxLength); - } else { - $pathOutput = $this->truncate(clean_path($path), $maxLength); - } - - $realPath = realpath($path); - $path = $realPath === false ? $path : $realPath; - - $tbody[] = [ - $ns, - $pathOutput, - is_dir($path) ? 'Yes' : 'MISSING', - ]; - } - } - - return $tbody; - } } diff --git a/tests/system/Commands/Utilities/NamespacesTest.php b/tests/system/Commands/Utilities/NamespacesTest.php index e519ca19d9bc..5f9c69182af2 100644 --- a/tests/system/Commands/Utilities/NamespacesTest.php +++ b/tests/system/Commands/Utilities/NamespacesTest.php @@ -89,7 +89,7 @@ public function testNamespacesCommandAllNamespaces(): void public function testTruncateNamespaces(): void { - $commandObject = new Namespaces(service('logger'), service('commands')); + $commandObject = new Namespaces(service('commands')); $truncateRunner = self::getPrivateMethodInvoker($commandObject, 'truncate'); $this->assertSame('App\Controllers\...', $truncateRunner('App\Controllers\Admin', 19)); diff --git a/user_guide_src/source/changelogs/v4.8.0.rst b/user_guide_src/source/changelogs/v4.8.0.rst index 1327ebdb2be5..c8a9e3e32bc3 100644 --- a/user_guide_src/source/changelogs/v4.8.0.rst +++ b/user_guide_src/source/changelogs/v4.8.0.rst @@ -222,6 +222,7 @@ Commands - Added ``key:rotate`` command to demote the current ``encryption.key`` to ``encryption.previousKeys`` in **.env** and generate a new key. See :ref:`spark-key-rotate`. - Added ``AbstractCommand::callSilently()`` to invoke another command with its output discarded, restoring the prior IO afterwards. See :ref:`modern-commands-call-silently`. - The ``migrate``, ``migrate:rollback``, ``migrate:refresh``, and ``migrate:status`` commands now accept long option names (``--namespace``, ``--group``, ``--batch``, ``--force``) alongside their existing short forms (``-n``, ``-g``, ``-b``, ``-f``). +- The ``namespaces`` command now accepts long option names (``--config-only``, ``--raw``, ``--max-length``) alongside its existing short forms (``-c``, ``-r``, ``-m``). - The ``worker:install`` and ``worker:uninstall`` commands now accept the ``-f`` short option alongside ``--force``. - Added :php:class:`NullInputOutput `, an :php:class:`InputOutput ` sink that discards all writes and returns an empty string from ``input()``. - The ``spark routes`` command now resolves the Before/After Filters columns for routes that use custom placeholders registered via ``$routes->addPlaceholder()``. diff --git a/utils/phpstan-baseline/loader.neon b/utils/phpstan-baseline/loader.neon index 9f91cd7a7101..817b59589b65 100644 --- a/utils/phpstan-baseline/loader.neon +++ b/utils/phpstan-baseline/loader.neon @@ -1,4 +1,4 @@ -# total 1496 errors +# total 1492 errors includes: - argument.type.neon diff --git a/utils/phpstan-baseline/missingType.iterableValue.neon b/utils/phpstan-baseline/missingType.iterableValue.neon index c8bb426bc340..b3af2d5046f0 100644 --- a/utils/phpstan-baseline/missingType.iterableValue.neon +++ b/utils/phpstan-baseline/missingType.iterableValue.neon @@ -1,4 +1,4 @@ -# total 1086 errors +# total 1082 errors parameters: ignoreErrors: @@ -7,26 +7,6 @@ parameters: count: 1 path: ../../system/CodeIgniter.php - - - message: '#^Method CodeIgniter\\Commands\\Utilities\\Namespaces\:\:outputAllNamespaces\(\) has parameter \$params with no value type specified in iterable type array\.$#' - count: 1 - path: ../../system/Commands/Utilities/Namespaces.php - - - - message: '#^Method CodeIgniter\\Commands\\Utilities\\Namespaces\:\:outputAllNamespaces\(\) return type has no value type specified in iterable type array\.$#' - count: 1 - path: ../../system/Commands/Utilities/Namespaces.php - - - - message: '#^Method CodeIgniter\\Commands\\Utilities\\Namespaces\:\:outputCINamespaces\(\) has parameter \$params with no value type specified in iterable type array\.$#' - count: 1 - path: ../../system/Commands/Utilities/Namespaces.php - - - - message: '#^Method CodeIgniter\\Commands\\Utilities\\Namespaces\:\:outputCINamespaces\(\) return type has no value type specified in iterable type array\.$#' - count: 1 - path: ../../system/Commands/Utilities/Namespaces.php - - message: '#^Method CodeIgniter\\Commands\\Utilities\\Routes\\AutoRouterImproved\\AutoRouteCollector\:\:addFilters\(\) has parameter \$routes with no value type specified in iterable type array\.$#' count: 1