From f8ee76dfb6f7f1b91509e00a3dcae8d74963d1c9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 28 Dec 2023 10:59:34 +0900 Subject: [PATCH 1/7] docs: make PHPDoc types more accurate --- system/Autoloader/Autoloader.php | 7 ++++--- system/Config/AutoloadConfig.php | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/system/Autoloader/Autoloader.php b/system/Autoloader/Autoloader.php index 4c6fed350fe2..c6ddd84f2efc 100644 --- a/system/Autoloader/Autoloader.php +++ b/system/Autoloader/Autoloader.php @@ -63,14 +63,14 @@ class Autoloader /** * Stores namespaces as key, and path as values. * - * @var array> + * @var array> */ protected $prefixes = []; /** * Stores class name as key, and path as values. * - * @var array + * @var array */ protected $classmap = []; @@ -215,7 +215,8 @@ public function addNamespace($namespace, ?string $path = null) * * If a prefix param is set, returns only paths to the given prefix. * - * @return array + * @return array>|list + * @phpstan-return ($prefix is null ? array> : list) */ public function getNamespace(?string $prefix = null) { diff --git a/system/Config/AutoloadConfig.php b/system/Config/AutoloadConfig.php index f70d07155613..e5f270a58702 100644 --- a/system/Config/AutoloadConfig.php +++ b/system/Config/AutoloadConfig.php @@ -106,7 +106,7 @@ class AutoloadConfig * searched for within one or more directories as they would if they * were being autoloaded through a namespace. * - * @var array + * @var array */ protected $coreClassmap = [ AbstractLogger::class => SYSTEMPATH . 'ThirdParty/PSR/Log/AbstractLogger.php', From 388173b7462b4b376a0f2f275fb35a93253a2c34 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 28 Dec 2023 11:05:41 +0900 Subject: [PATCH 2/7] config: add namespace paths for test classes --- app/Config/Autoload.php | 2 +- system/Config/AutoloadConfig.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php index 76cd9263556e..784121fdd04d 100644 --- a/app/Config/Autoload.php +++ b/app/Config/Autoload.php @@ -40,7 +40,7 @@ class Autoload extends AutoloadConfig * @var array|string> */ public $psr4 = [ - APP_NAMESPACE => APPPATH, + APP_NAMESPACE => [APPPATH, TESTPATH . 'app'], ]; /** diff --git a/system/Config/AutoloadConfig.php b/system/Config/AutoloadConfig.php index e5f270a58702..3866ce760a56 100644 --- a/system/Config/AutoloadConfig.php +++ b/system/Config/AutoloadConfig.php @@ -91,7 +91,7 @@ class AutoloadConfig * @var array */ protected $corePsr4 = [ - 'CodeIgniter' => SYSTEMPATH, + 'CodeIgniter' => [SYSTEMPATH, TESTPATH . 'system'], 'Config' => APPPATH . 'Config', 'Tests' => ROOTPATH . 'tests', ]; From ae88a3582b7bb10c081bb1aeee6cfcaa59fce05e Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 28 Dec 2023 11:07:37 +0900 Subject: [PATCH 3/7] feat: support multiple paths for namespace "CodeIgniter" --- system/Autoloader/FileLocator.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/system/Autoloader/FileLocator.php b/system/Autoloader/FileLocator.php index 37a13e159557..e37832f4c08c 100644 --- a/system/Autoloader/FileLocator.php +++ b/system/Autoloader/FileLocator.php @@ -237,7 +237,7 @@ protected function getNamespaces() foreach ($this->autoloader->getNamespace() as $prefix => $paths) { foreach ($paths as $path) { if ($prefix === 'CodeIgniter') { - $system = [ + $system[] = [ 'prefix' => $prefix, 'path' => rtrim($path, '\\/') . DIRECTORY_SEPARATOR, ]; @@ -252,9 +252,7 @@ protected function getNamespaces() } } - $namespaces[] = $system; - - return $namespaces; + return array_merge($namespaces, $system); } /** From 08cf3a70704303024e7f2b919c72f7abb286ca9e Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 28 Dec 2023 11:08:16 +0900 Subject: [PATCH 4/7] feat: make:test creates test files in /tests/ directories --- system/Commands/Generators/TestGenerator.php | 68 +++++++++++++++++++- tests/system/Commands/TestGeneratorTest.php | 2 +- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/system/Commands/Generators/TestGenerator.php b/system/Commands/Generators/TestGenerator.php index d09ecda5ae83..60863886e121 100644 --- a/system/Commands/Generators/TestGenerator.php +++ b/system/Commands/Generators/TestGenerator.php @@ -14,7 +14,9 @@ namespace CodeIgniter\Commands\Generators; use CodeIgniter\CLI\BaseCommand; +use CodeIgniter\CLI\CLI; use CodeIgniter\CLI\GeneratorTrait; +use Config\Services; /** * Generates a skeleton command file. @@ -66,7 +68,8 @@ class TestGenerator extends BaseCommand * @var array */ protected $options = [ - '--force' => 'Force overwrite existing file.', + '--namespace' => 'Set root namespace. Default: "APP_NAMESPACE".', + '--force' => 'Force overwrite existing file.', ]; /** @@ -76,9 +79,70 @@ 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); } + + /** + * Builds the test file path from the class name. + * + * @param string $class namespaced classname or namespaced view. + */ + protected function buildPath(string $class): string + { + $namespace = $this->getNamespace(); + + $base = $this->searchTestFilePath($namespace); + + if ($base === null) { + CLI::error( + lang('CLI.namespaceNotDefined', [$namespace]), + 'light_gray', + 'red' + ); + CLI::newLine(); + + return ''; + } + + $realpath = realpath($base); + $base = ($realpath !== false) ? $realpath : $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); + } + + /** + * Returns test file path for the namespace. + */ + private function searchTestFilePath(string $namespace): ?string + { + $bases = Services::autoloader()->getNamespace($namespace); + + $base = null; + + foreach ($bases as $candidate) { + if (str_contains($candidate, '/tests/')) { + $base = $candidate; + + break; + } + } + + return $base; + } } diff --git a/tests/system/Commands/TestGeneratorTest.php b/tests/system/Commands/TestGeneratorTest.php index 8ffe89c3de55..888d8b03d1a1 100644 --- a/tests/system/Commands/TestGeneratorTest.php +++ b/tests/system/Commands/TestGeneratorTest.php @@ -41,6 +41,6 @@ protected function tearDown(): void public function testGenerateTest(): void { command('make:test Foo/Bar'); - $this->assertFileExists(ROOTPATH . 'tests/Foo/Bar.php'); + $this->assertFileExists(ROOTPATH . 'tests/app/Foo/Bar.php'); } } From 14cf7ccdb2607df45fc7abc4cf83d9c9dd5f5e8a Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 28 Dec 2023 11:25:12 +0900 Subject: [PATCH 5/7] docs: update docs --- user_guide_src/source/cli/cli_generators.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/user_guide_src/source/cli/cli_generators.rst b/user_guide_src/source/cli/cli_generators.rst index 2f8d7c9d55bf..ff539b3c848d 100644 --- a/user_guide_src/source/cli/cli_generators.rst +++ b/user_guide_src/source/cli/cli_generators.rst @@ -248,6 +248,7 @@ Argument: Options: ======== +* ``--namespace``: Set the root namespace. Defaults to value of ``APP_NAMESPACE``. * ``--force``: Set this flag to overwrite existing files on destination. make:migration From e765fae551f8f77eccdc68f62af3a62952b90c45 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 28 Dec 2023 11:50:50 +0900 Subject: [PATCH 6/7] test: update test assertions --- tests/system/Autoloader/AutoloaderTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/Autoloader/AutoloaderTest.php b/tests/system/Autoloader/AutoloaderTest.php index fbefbe20b0ef..6a1b496b05c9 100644 --- a/tests/system/Autoloader/AutoloaderTest.php +++ b/tests/system/Autoloader/AutoloaderTest.php @@ -97,13 +97,13 @@ public function testInitializeTwice(): void $loader->initialize(new Autoload(), new Modules()); $ns = $loader->getNamespace(); - $this->assertCount(1, $ns['App']); + $this->assertCount(2, $ns['App']); $this->assertSame('ROOTPATH/app', clean_path($ns['App'][0])); $loader->initialize(new Autoload(), new Modules()); $ns = $loader->getNamespace(); - $this->assertCount(1, $ns['App']); + $this->assertCount(2, $ns['App']); $this->assertSame('ROOTPATH/app', clean_path($ns['App'][0])); } From 6165794802cd98d4c8d34193b12e14494d2b711e Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 28 Dec 2023 11:51:57 +0900 Subject: [PATCH 7/7] fix: make sure return value is a list --- system/Autoloader/FileLocator.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/Autoloader/FileLocator.php b/system/Autoloader/FileLocator.php index e37832f4c08c..f176bd6c0d7e 100644 --- a/system/Autoloader/FileLocator.php +++ b/system/Autoloader/FileLocator.php @@ -175,6 +175,8 @@ public function getClassname(string $file): string * 'app/Modules/foo/Config/Routes.php', * 'app/Modules/bar/Config/Routes.php', * ] + * + * @return list */ public function search(string $path, string $ext = 'php', bool $prioritizeApp = true): array { @@ -203,7 +205,7 @@ public function search(string $path, string $ext = 'php', bool $prioritizeApp = } // Remove any duplicates - return array_unique($foundPaths); + return array_values(array_unique($foundPaths)); } /**