From 9eaf09b6328a246e6cfcd9d8b47026fbb721d7b5 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Mon, 31 Oct 2022 08:33:06 +0330 Subject: [PATCH 1/7] feat: add new CLI command for make custom `UserModel` --- docs/concepts.md | 12 ++- .../Generators/UserModelGenerator.php | 77 ++++++++++++++ .../Generators/Views/usermodel.tpl.php | 20 ++++ src/Config/Registrar.php | 9 ++ tests/Commands/UserModelGeneratorTest.php | 100 ++++++++++++++++++ 5 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 src/Commands/Generators/UserModelGenerator.php create mode 100644 src/Commands/Generators/Views/usermodel.tpl.php create mode 100644 tests/Commands/UserModelGeneratorTest.php diff --git a/docs/concepts.md b/docs/concepts.md index 073038885..6307a7200 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -25,11 +25,19 @@ on the standard Config class if nothing is found in the database. ## User Providers You can use your own models to handle user persistence. Shield calls this the "User Provider" class. A default model -is provided for you at `CodeIgniter\Shield\Models\UserModel`. You can change this in the `Config\Auth::$userProvider` setting. +is provided for you at `CodeIgniter\Shield\Models\UserModel`. You can change this in the `Config\Auth->userProvider` setting. The only requirement is that your new class MUST extend the provided `UserModel`. +Shield has a CLI command to quickly create a custom `MyUserModel` by running the following command in terminal: + +```console +php spark shield:model MyUserModel +``` + +You should set `Config\Auth::$userProvider` as follows: + ```php -public string $userProvider = UserModel::class; +public string $userProvider = \App\Models\MyUserModel::class; ``` ## User Identities diff --git a/src/Commands/Generators/UserModelGenerator.php b/src/Commands/Generators/UserModelGenerator.php new file mode 100644 index 000000000..f792abe26 --- /dev/null +++ b/src/Commands/Generators/UserModelGenerator.php @@ -0,0 +1,77 @@ + [options]'; + + /** + * The Command's Arguments + * + * @var array + */ + protected $arguments = [ + 'name' => 'The model class name.', + ]; + + /** + * The Command's Options + * + * @var array + */ + protected $options = [ + '--namespace' => 'Set root namespace. Default: "APP_NAMESPACE".', + '--suffix' => 'Append the component title to the class name (e.g. User => UserModel).', + '--force' => 'Force overwrite existing file.', + ]; + + /** + * Actually execute a command. + */ + public function run(array $params): void + { + $this->component = 'Model'; + $this->directory = 'Models'; + $this->template = 'usermodel.tpl.php'; + + $this->classNameLang = 'CLI.generator.className.model'; + $this->execute($params); + } +} diff --git a/src/Commands/Generators/Views/usermodel.tpl.php b/src/Commands/Generators/Views/usermodel.tpl.php new file mode 100644 index 000000000..e25f6cb1a --- /dev/null +++ b/src/Commands/Generators/Views/usermodel.tpl.php @@ -0,0 +1,20 @@ +<@php + +declare(strict_types=1); + +namespace {namespace}; + +use CodeIgniter\Shield\Models\UserModel; + +class {class} extends UserModel +{ + protected function initialize(): void + { + $this->allowedFields = [ + ...$this->allowedFields, + // Add here your custom fields + // 'first_name', + ]; + } +} + diff --git a/src/Config/Registrar.php b/src/Config/Registrar.php index f05263c9c..b22ec0a30 100644 --- a/src/Config/Registrar.php +++ b/src/Config/Registrar.php @@ -49,4 +49,13 @@ public static function Toolbar(): array ], ]; } + + public static function Generators(): array + { + return [ + 'views' => [ + 'shield:model' => 'CodeIgniter\Shield\Commands\Generators\Views\usermodel.tpl.php', + ], + ]; + } } diff --git a/tests/Commands/UserModelGeneratorTest.php b/tests/Commands/UserModelGeneratorTest.php new file mode 100644 index 000000000..bb8e74b4e --- /dev/null +++ b/tests/Commands/UserModelGeneratorTest.php @@ -0,0 +1,100 @@ +streamFilter = stream_filter_append(STDOUT, 'CITestStreamFilter'); + $this->streamFilter = stream_filter_append(STDERR, 'CITestStreamFilter'); + } + + protected function tearDown(): void + { + parent::tearDown(); + + stream_filter_remove($this->streamFilter); + $result = str_replace(["\033[0;32m", "\033[0m", "\n"], '', CITestStreamFilter::$buffer); + + $filepath = str_replace('APPPATH' . DIRECTORY_SEPARATOR, APPPATH, trim(substr($result, 14))); + if (is_file($filepath)) { + unlink($filepath); + } + } + + protected function getFileContents(string $filepath): string + { + if (! file_exists($filepath)) { + return ''; + } + + return file_get_contents($filepath) ?: ''; + } + + public function testGenerateUserModel(): void + { + command('shield:model MyUserModel'); + $filepath = APPPATH . 'Models/MyUserModel.php'; + + $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); + $this->assertFileExists($filepath); + + $this->assertStringContainsString('namespace App\Models;', $this->getFileContents($filepath)); + $this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath)); + $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $this->getFileContents($filepath)); + $this->assertStringContainsString('protected function initialize(): void', $this->getFileContents($filepath)); + } + + public function testGenerateUserModelCustomNamespace(): void + { + command('shield:model MyUserModel --namespace CodeIgniter\\\\Shield'); + $filepath = HOMEPATH . 'src/Models/MyUserModel.php'; + + $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); + $this->assertFileExists($filepath); + + $this->assertStringContainsString('namespace CodeIgniter\Shield\Models;', $this->getFileContents($filepath)); + $this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath)); + $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $this->getFileContents($filepath)); + $this->assertStringContainsString('protected function initialize(): void', $this->getFileContents($filepath)); + + if (is_file($filepath)) { + unlink($filepath); + } + } + + public function testGenerateUserModelWithForce(): void + { + command('shield:model MyUserModel'); + + command('shield:model MyUserModel --force'); + $this->assertStringContainsString('File overwritten: ', CITestStreamFilter::$buffer); + + $filepath = APPPATH . 'Models/MyUserModel.php'; + $this->assertFileExists($filepath); + } + + public function testGenerateUserModelWithSuffix(): void + { + command('shield:model MyUser --suffix'); + $filepath = APPPATH . 'Models/MyUserModel.php'; + + $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); + $this->assertFileExists($filepath); + $this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath)); + } +} From 080299b13ab9b2d7270e516db2cc6d6130cb34a5 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 13 Dec 2022 14:11:43 +0800 Subject: [PATCH 2/7] Remove unnecessary comments. --- src/Commands/Generators/UserModelGenerator.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/Commands/Generators/UserModelGenerator.php b/src/Commands/Generators/UserModelGenerator.php index f792abe26..e22529cd3 100644 --- a/src/Commands/Generators/UserModelGenerator.php +++ b/src/Commands/Generators/UserModelGenerator.php @@ -8,36 +8,28 @@ use CodeIgniter\CLI\GeneratorTrait; /** - * Generates a skeleton command file. + * Generates a custom user model file. */ class UserModelGenerator extends BaseCommand { use GeneratorTrait; /** - * The Command's Group - * * @var string */ protected $group = 'Shield'; /** - * The Command's Name - * * @var string */ protected $name = 'shield:model'; /** - * The Command's Description - * * @var string */ - protected $description = 'Generates a new UserModel file.'; + protected $description = 'Generate a new UserModel file.'; /** - * The Command's Usage - * * @var string */ protected $usage = 'shield:model [options]'; @@ -52,8 +44,6 @@ class UserModelGenerator extends BaseCommand ]; /** - * The Command's Options - * * @var array */ protected $options = [ @@ -63,7 +53,7 @@ class UserModelGenerator extends BaseCommand ]; /** - * Actually execute a command. + * Actually execute the command. */ public function run(array $params): void { @@ -72,6 +62,7 @@ public function run(array $params): void $this->template = 'usermodel.tpl.php'; $this->classNameLang = 'CLI.generator.className.model'; + $this->execute($params); } } From f798f25d18e38e848f50c65af7d03a633b780f8e Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 13 Dec 2022 14:13:03 +0800 Subject: [PATCH 3/7] Fix tests to be compatible with randomized testing --- tests/Commands/UserModelGeneratorTest.php | 71 +++++++++++++---------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/tests/Commands/UserModelGeneratorTest.php b/tests/Commands/UserModelGeneratorTest.php index bb8e74b4e..96d03aa34 100644 --- a/tests/Commands/UserModelGeneratorTest.php +++ b/tests/Commands/UserModelGeneratorTest.php @@ -12,15 +12,18 @@ */ final class UserModelGeneratorTest extends CIUnitTestCase { - protected $streamFilter; + private $streamFilter; protected function setUp(): void { parent::setUp(); CITestStreamFilter::$buffer = ''; - $this->streamFilter = stream_filter_append(STDOUT, 'CITestStreamFilter'); - $this->streamFilter = stream_filter_append(STDERR, 'CITestStreamFilter'); + + $this->streamFilter = stream_filter_append(STDOUT, 'CITestStreamFilter'); + $this->streamFilter = stream_filter_append(STDERR, 'CITestStreamFilter'); + + $this->deleteTestFiles(); } protected function tearDown(): void @@ -28,72 +31,76 @@ protected function tearDown(): void parent::tearDown(); stream_filter_remove($this->streamFilter); - $result = str_replace(["\033[0;32m", "\033[0m", "\n"], '', CITestStreamFilter::$buffer); - - $filepath = str_replace('APPPATH' . DIRECTORY_SEPARATOR, APPPATH, trim(substr($result, 14))); - if (is_file($filepath)) { - unlink($filepath); - } + $this->deleteTestFiles(); } - protected function getFileContents(string $filepath): string + private function deleteTestFiles(): void { - if (! file_exists($filepath)) { - return ''; + $possibleFiles = [ + APPPATH . 'Models/MyUserModel.php', + HOMEPATH . 'src/Models/MyUserModel.php', + ]; + + foreach ($possibleFiles as $file) { + clearstatcache(true, $file); + + if (is_file($file)) { + unlink($file); + } } + } - return file_get_contents($filepath) ?: ''; + private function getFileContents(string $filepath): string + { + return (string) @file_get_contents($filepath); } public function testGenerateUserModel(): void { command('shield:model MyUserModel'); - $filepath = APPPATH . 'Models/MyUserModel.php'; + $filepath = APPPATH . 'Models/MyUserModel.php'; $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); $this->assertFileExists($filepath); - $this->assertStringContainsString('namespace App\Models;', $this->getFileContents($filepath)); - $this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath)); - $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $this->getFileContents($filepath)); - $this->assertStringContainsString('protected function initialize(): void', $this->getFileContents($filepath)); + $contents = $this->getFileContents($filepath); + $this->assertStringContainsString('namespace App\Models;', $contents); + $this->assertStringContainsString('class MyUserModel extends UserModel', $contents); + $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $contents); + $this->assertStringContainsString('protected function initialize(): void', $contents); } public function testGenerateUserModelCustomNamespace(): void { command('shield:model MyUserModel --namespace CodeIgniter\\\\Shield'); - $filepath = HOMEPATH . 'src/Models/MyUserModel.php'; + $filepath = HOMEPATH . 'src/Models/MyUserModel.php'; $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); $this->assertFileExists($filepath); - $this->assertStringContainsString('namespace CodeIgniter\Shield\Models;', $this->getFileContents($filepath)); - $this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath)); - $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $this->getFileContents($filepath)); - $this->assertStringContainsString('protected function initialize(): void', $this->getFileContents($filepath)); - - if (is_file($filepath)) { - unlink($filepath); - } + $contents = $this->getFileContents($filepath); + $this->assertStringContainsString('namespace CodeIgniter\Shield\Models;', $contents); + $this->assertStringContainsString('class MyUserModel extends UserModel', $contents); + $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $contents); + $this->assertStringContainsString('protected function initialize(): void', $contents); } public function testGenerateUserModelWithForce(): void { command('shield:model MyUserModel'); - command('shield:model MyUserModel --force'); - $this->assertStringContainsString('File overwritten: ', CITestStreamFilter::$buffer); - $filepath = APPPATH . 'Models/MyUserModel.php'; - $this->assertFileExists($filepath); + $this->assertStringContainsString('File overwritten: ', CITestStreamFilter::$buffer); + $this->assertFileExists(APPPATH . 'Models/MyUserModel.php'); } public function testGenerateUserModelWithSuffix(): void { command('shield:model MyUser --suffix'); - $filepath = APPPATH . 'Models/MyUserModel.php'; $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); + + $filepath = APPPATH . 'Models/MyUserModel.php'; $this->assertFileExists($filepath); $this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath)); } From 4afdab055ff5d6b31de1d1a4412f9439affae3fc Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Tue, 13 Dec 2022 14:39:21 +0800 Subject: [PATCH 4/7] Fix concepts.md --- docs/concepts.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/concepts.md b/docs/concepts.md index 6307a7200..0dd556727 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -24,11 +24,13 @@ on the standard Config class if nothing is found in the database. ## User Providers -You can use your own models to handle user persistence. Shield calls this the "User Provider" class. A default model -is provided for you at `CodeIgniter\Shield\Models\UserModel`. You can change this in the `Config\Auth->userProvider` setting. -The only requirement is that your new class MUST extend the provided `UserModel`. +You can use your own models to handle user persistence. Shield calls this the "User Provider" class. +A default model is provided for you by the `CodeIgniter\Shield\Models\UserModel` class. You can change +this in the `Config\Auth::$userProvider` setting. The only requirement is that your new class +MUST extend the provided `UserModel`. -Shield has a CLI command to quickly create a custom `MyUserModel` by running the following command in terminal: +Shield has a CLI command to quickly create a custom `MyUserModel` class by running the following +command in the terminal: ```console php spark shield:model MyUserModel From fbadd42b7d0747fb84fee9cafd2aa11c8a9e0c22 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Mon, 2 Jan 2023 13:45:39 +0800 Subject: [PATCH 5/7] Use `UserModel` as test class name --- docs/concepts.md | 6 +-- .../Generators/Views/usermodel.tpl.php | 7 ++-- tests/Commands/UserModelGeneratorTest.php | 41 +++++++++++-------- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/docs/concepts.md b/docs/concepts.md index 0dd556727..6ea670b9e 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -29,17 +29,17 @@ A default model is provided for you by the `CodeIgniter\Shield\Models\UserModel` this in the `Config\Auth::$userProvider` setting. The only requirement is that your new class MUST extend the provided `UserModel`. -Shield has a CLI command to quickly create a custom `MyUserModel` class by running the following +Shield has a CLI command to quickly create a custom `UserModel` class by running the following command in the terminal: ```console -php spark shield:model MyUserModel +php spark shield:model UserModel ``` You should set `Config\Auth::$userProvider` as follows: ```php -public string $userProvider = \App\Models\MyUserModel::class; +public string $userProvider = \App\Models\UserModel::class; ``` ## User Identities diff --git a/src/Commands/Generators/Views/usermodel.tpl.php b/src/Commands/Generators/Views/usermodel.tpl.php index e25f6cb1a..8937a2978 100644 --- a/src/Commands/Generators/Views/usermodel.tpl.php +++ b/src/Commands/Generators/Views/usermodel.tpl.php @@ -4,17 +4,16 @@ namespace {namespace}; -use CodeIgniter\Shield\Models\UserModel; +use CodeIgniter\Shield\Models\UserModel as ShieldUserModel; -class {class} extends UserModel +class {class} extends ShieldUserModel { protected function initialize(): void { $this->allowedFields = [ ...$this->allowedFields, - // Add here your custom fields + // 'first_name', ]; } } - diff --git a/tests/Commands/UserModelGeneratorTest.php b/tests/Commands/UserModelGeneratorTest.php index 96d03aa34..3d6360992 100644 --- a/tests/Commands/UserModelGeneratorTest.php +++ b/tests/Commands/UserModelGeneratorTest.php @@ -23,6 +23,10 @@ protected function setUp(): void $this->streamFilter = stream_filter_append(STDOUT, 'CITestStreamFilter'); $this->streamFilter = stream_filter_append(STDERR, 'CITestStreamFilter'); + if (is_file(HOMEPATH . 'src/Models/UserModel.php')) { + copy(HOMEPATH . 'src/Models/UserModel.php', HOMEPATH . 'src/Models/UserModel.php.bak'); + } + $this->deleteTestFiles(); } @@ -32,13 +36,18 @@ protected function tearDown(): void stream_filter_remove($this->streamFilter); $this->deleteTestFiles(); + + if (is_file(HOMEPATH . 'src/Models/UserModel.php.bak')) { + copy(HOMEPATH . 'src/Models/UserModel.php.bak', HOMEPATH . 'src/Models/UserModel.php'); + unlink(HOMEPATH . 'src/Models/UserModel.php.bak'); + } } private function deleteTestFiles(): void { $possibleFiles = [ - APPPATH . 'Models/MyUserModel.php', - HOMEPATH . 'src/Models/MyUserModel.php', + APPPATH . 'Models/UserModel.php', + HOMEPATH . 'src/Models/UserModel.php', ]; foreach ($possibleFiles as $file) { @@ -57,51 +66,51 @@ private function getFileContents(string $filepath): string public function testGenerateUserModel(): void { - command('shield:model MyUserModel'); + command('shield:model UserModel'); - $filepath = APPPATH . 'Models/MyUserModel.php'; + $filepath = APPPATH . 'Models/UserModel.php'; $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); $this->assertFileExists($filepath); $contents = $this->getFileContents($filepath); $this->assertStringContainsString('namespace App\Models;', $contents); - $this->assertStringContainsString('class MyUserModel extends UserModel', $contents); - $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $contents); + $this->assertStringContainsString('class UserModel extends ShieldUserModel', $contents); + $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel as ShieldUserModel;', $contents); $this->assertStringContainsString('protected function initialize(): void', $contents); } public function testGenerateUserModelCustomNamespace(): void { - command('shield:model MyUserModel --namespace CodeIgniter\\\\Shield'); + command('shield:model UserModel --namespace CodeIgniter\\\\Shield'); - $filepath = HOMEPATH . 'src/Models/MyUserModel.php'; + $filepath = HOMEPATH . 'src/Models/UserModel.php'; $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); $this->assertFileExists($filepath); $contents = $this->getFileContents($filepath); $this->assertStringContainsString('namespace CodeIgniter\Shield\Models;', $contents); - $this->assertStringContainsString('class MyUserModel extends UserModel', $contents); - $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel;', $contents); + $this->assertStringContainsString('class UserModel extends ShieldUserModel', $contents); + $this->assertStringContainsString('use CodeIgniter\Shield\Models\UserModel as ShieldUserModel;', $contents); $this->assertStringContainsString('protected function initialize(): void', $contents); } public function testGenerateUserModelWithForce(): void { - command('shield:model MyUserModel'); - command('shield:model MyUserModel --force'); + command('shield:model UserModel'); + command('shield:model UserModel --force'); $this->assertStringContainsString('File overwritten: ', CITestStreamFilter::$buffer); - $this->assertFileExists(APPPATH . 'Models/MyUserModel.php'); + $this->assertFileExists(APPPATH . 'Models/UserModel.php'); } public function testGenerateUserModelWithSuffix(): void { - command('shield:model MyUser --suffix'); + command('shield:model User --suffix'); $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); - $filepath = APPPATH . 'Models/MyUserModel.php'; + $filepath = APPPATH . 'Models/UserModel.php'; $this->assertFileExists($filepath); - $this->assertStringContainsString('class MyUserModel extends UserModel', $this->getFileContents($filepath)); + $this->assertStringContainsString('class UserModel extends ShieldUserModel', $this->getFileContents($filepath)); } } From 718dd4e5bc8ff41520b9728f05833fe3090596cb Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Mon, 2 Jan 2023 14:08:19 +0800 Subject: [PATCH 6/7] Make the class name input optional with default. --- docs/concepts.md | 2 ++ .../Generators/UserModelGenerator.php | 18 ++++++++++--- tests/Commands/UserModelGeneratorTest.php | 26 +++++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/docs/concepts.md b/docs/concepts.md index 6ea670b9e..97ab1612b 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -36,6 +36,8 @@ command in the terminal: php spark shield:model UserModel ``` +The class name is optional. If none is provided, the generated class name would be `UserModel`. + You should set `Config\Auth::$userProvider` as follows: ```php diff --git a/src/Commands/Generators/UserModelGenerator.php b/src/Commands/Generators/UserModelGenerator.php index e22529cd3..ee59d1c3d 100644 --- a/src/Commands/Generators/UserModelGenerator.php +++ b/src/Commands/Generators/UserModelGenerator.php @@ -5,6 +5,7 @@ namespace CodeIgniter\Shield\Commands\Generators; use CodeIgniter\CLI\BaseCommand; +use CodeIgniter\CLI\CLI; use CodeIgniter\CLI\GeneratorTrait; /** @@ -32,15 +33,13 @@ class UserModelGenerator extends BaseCommand /** * @var string */ - protected $usage = 'shield:model [options]'; + protected $usage = 'shield:model [] [options]'; /** - * The Command's Arguments - * * @var array */ protected $arguments = [ - 'name' => 'The model class name.', + 'name' => 'The model class name. If not provided, this will default to `UserModel`.', ]; /** @@ -62,6 +61,17 @@ public function run(array $params): void $this->template = 'usermodel.tpl.php'; $this->classNameLang = 'CLI.generator.className.model'; + $this->setHasClassName(false); + + $class = $params[0] ?? CLI::getSegment(2) ?? 'UserModel'; + + if (in_array(strtolower($class), ['shielduser', 'shieldusermodel'], true)) { + CLI::error('Cannot use `ShieldUserModel` as class name as this conflicts with the parent class.', 'light_gray', 'red'); + + return; // @TODO when CI4 is at v4.3+, change this to `return 1;` to signify failing exit + } + + $params[0] = $class; $this->execute($params); } diff --git a/tests/Commands/UserModelGeneratorTest.php b/tests/Commands/UserModelGeneratorTest.php index 3d6360992..cf009e373 100644 --- a/tests/Commands/UserModelGeneratorTest.php +++ b/tests/Commands/UserModelGeneratorTest.php @@ -113,4 +113,30 @@ public function testGenerateUserModelWithSuffix(): void $this->assertFileExists($filepath); $this->assertStringContainsString('class UserModel extends ShieldUserModel', $this->getFileContents($filepath)); } + + public function testGenerateUserModelWithoutClassNameInput(): void + { + command('shield:model'); + + $this->assertStringContainsString('File created: ', CITestStreamFilter::$buffer); + + $filepath = APPPATH . 'Models/UserModel.php'; + $this->assertFileExists($filepath); + $this->assertStringContainsString('class UserModel extends ShieldUserModel', $this->getFileContents($filepath)); + } + + public function testGenerateUserCannotAcceptShieldUserModelAsInput(): void + { + command('shield:model ShieldUserModel'); + + $this->assertStringContainsString('Cannot use `ShieldUserModel` as class name as this conflicts with the parent class.', CITestStreamFilter::$buffer); + $this->assertFileDoesNotExist(APPPATH . 'Models/UserModel.php'); + + CITestStreamFilter::$buffer = ''; + + command('shield:model ShieldUser --suffix'); + + $this->assertStringContainsString('Cannot use `ShieldUserModel` as class name as this conflicts with the parent class.', CITestStreamFilter::$buffer); + $this->assertFileDoesNotExist(APPPATH . 'Models/UserModel.php'); + } } From 7e5c4a2069cf570f7e08b934a0f7633c17f7c12e Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Thu, 5 Jan 2023 10:24:43 +0800 Subject: [PATCH 7/7] Add conditional check when suffix option is given --- src/Commands/Generators/UserModelGenerator.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Commands/Generators/UserModelGenerator.php b/src/Commands/Generators/UserModelGenerator.php index ee59d1c3d..fdb76596c 100644 --- a/src/Commands/Generators/UserModelGenerator.php +++ b/src/Commands/Generators/UserModelGenerator.php @@ -65,7 +65,7 @@ public function run(array $params): void $class = $params[0] ?? CLI::getSegment(2) ?? 'UserModel'; - if (in_array(strtolower($class), ['shielduser', 'shieldusermodel'], true)) { + if (! $this->verifyChosenModelClassName($class, $params)) { CLI::error('Cannot use `ShieldUserModel` as class name as this conflicts with the parent class.', 'light_gray', 'red'); return; // @TODO when CI4 is at v4.3+, change this to `return 1;` to signify failing exit @@ -75,4 +75,18 @@ public function run(array $params): void $this->execute($params); } + + /** + * The chosen class name should not conflict with the alias of the parent class. + */ + private function verifyChosenModelClassName(string $class, array $params): bool + { + helper('inflector'); + + if (array_key_exists('suffix', $params) && ! strripos($class, 'Model')) { + $class .= 'Model'; + } + + return strtolower(pascalize($class)) !== 'shieldusermodel'; + } }