From 1ac4f0ecd14e3cd6047543b6260375b5b5cd58e2 Mon Sep 17 00:00:00 2001 From: mscherer Date: Sat, 23 Dec 2023 00:01:59 +0100 Subject: [PATCH 1/8] Allow baking enums. --- docs/en/usage.rst | 2 + src/Command/EnumCommand.php | 54 +++++++++++++++++++++ templates/bake/Model/enum.twig | 30 ++++++++++++ tests/TestCase/Command/EnumCommandTest.php | 55 ++++++++++++++++++++++ tests/comparisons/Model/testBakeEnum.php | 18 +++++++ 5 files changed, 159 insertions(+) create mode 100644 src/Command/EnumCommand.php create mode 100644 templates/bake/Model/enum.twig create mode 100644 tests/TestCase/Command/EnumCommandTest.php create mode 100644 tests/comparisons/Model/testBakeEnum.php diff --git a/docs/en/usage.rst b/docs/en/usage.rst index e25b3f02..29da6dcb 100644 --- a/docs/en/usage.rst +++ b/docs/en/usage.rst @@ -31,9 +31,11 @@ You can get the list of available bake command by running ``bin/cake bake --help - bake behavior - bake cell - bake command + - bake command_helper - bake component - bake controller - bake controller all + - bake enum - bake fixture - bake fixture all - bake form diff --git a/src/Command/EnumCommand.php b/src/Command/EnumCommand.php new file mode 100644 index 00000000..793aff44 --- /dev/null +++ b/src/Command/EnumCommand.php @@ -0,0 +1,54 @@ +name); + } +} diff --git a/tests/TestCase/Command/EnumCommandTest.php b/tests/TestCase/Command/EnumCommandTest.php new file mode 100644 index 00000000..df9d8dd2 --- /dev/null +++ b/tests/TestCase/Command/EnumCommandTest.php @@ -0,0 +1,55 @@ +_compareBasePath = Plugin::path('Bake') . 'tests' . DS . 'comparisons' . DS . 'Model' . DS; + $this->setAppNamespace('Bake\Test\App'); + } + + /** + * test baking an enum + * + * @return void + */ + public function testBakeEnum() + { + $this->generatedFile = APP . 'Model/Enum/FooBar.php'; + $this->exec('bake enum FooBar', ['y']); + + $this->assertExitCode(CommandInterface::CODE_SUCCESS); + $this->assertFileExists($this->generatedFile); + $result = file_get_contents($this->generatedFile); + $this->assertSameAsFile(__FUNCTION__ . '.php', $result); + } +} diff --git a/tests/comparisons/Model/testBakeEnum.php b/tests/comparisons/Model/testBakeEnum.php new file mode 100644 index 00000000..85e7e34b --- /dev/null +++ b/tests/comparisons/Model/testBakeEnum.php @@ -0,0 +1,18 @@ +name); + } +} From d10bd7ce4fbf1282dffe7f9bb95db4c650247222 Mon Sep 17 00:00:00 2001 From: mscherer Date: Sat, 23 Dec 2023 14:35:07 +0100 Subject: [PATCH 2/8] Allow baking enums. --- src/Command/EnumCommand.php | 45 +++++++++++++++++++ templates/bake/Model/enum.twig | 8 +++- tests/TestCase/Command/EnumCommandTest.php | 32 +++++++++++++ tests/comparisons/Model/testBakeEnum.php | 7 ++- .../comparisons/Model/testBakeEnumBacked.php | 21 +++++++++ .../Model/testBakeEnumBackedInt.php | 21 +++++++++ 6 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 tests/comparisons/Model/testBakeEnumBacked.php create mode 100644 tests/comparisons/Model/testBakeEnumBackedInt.php diff --git a/src/Command/EnumCommand.php b/src/Command/EnumCommand.php index 793aff44..34a4c9a1 100644 --- a/src/Command/EnumCommand.php +++ b/src/Command/EnumCommand.php @@ -16,6 +16,10 @@ */ namespace Bake\Command; +use Cake\Console\Arguments; +use Cake\Console\ConsoleOptionParser; +use InvalidArgumentException; + /** * Enum code generator. */ @@ -51,4 +55,45 @@ public function template(): string { return 'Bake.Model/enum'; } + + /** + * Get template data. + * + * @param \Cake\Console\Arguments $arguments The arguments for the command + * @return array + * @phpstan-return array + */ + public function templateData(Arguments $arguments): array + { + $data = parent::templateData($arguments); + + $backed = $arguments->getOption('backed'); + if ($backed && !in_array($backed, ['string', 'int'], true)) { + throw new InvalidArgumentException('Backed enums must be of type `string` or `int`'); + } + + $data['backed'] = $backed; + + return $data; + } + + /** + * Gets the option parser instance and configures it. + * + * @param \Cake\Console\ConsoleOptionParser $parser The option parser to update. + * @return \Cake\Console\ConsoleOptionParser + */ + public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser + { + $parser = $this->_setCommonOptions($parser); + + $parser->setDescription( + 'Bake (backed) enums for use in models.' + )->addOption('backed', [ + 'help' => 'If using backed enums. Set to `string` or `int`.', + 'short' => 'b', + ]); + + return $parser; + } } diff --git a/templates/bake/Model/enum.twig b/templates/bake/Model/enum.twig index 55f2b241..00217c18 100644 --- a/templates/bake/Model/enum.twig +++ b/templates/bake/Model/enum.twig @@ -15,16 +15,20 @@ #} {{ element('Bake.file_header', { namespace: "#{namespace}\\Model\\Enum", + classImports: [ + 'Cake\\Database\\Type\\EnumLabelInterface', + 'Cake\\Utility\\Inflector', + ], }) }} {{ DocBlock.classDescription(name, 'Enum', [])|raw }} -enum {{ name }}: int +enum {{ name }}{{ backed ? ': ' ~ backed : ''}} implements EnumLabelInterface { /** * @return string */ public function label(): string { - return mb_strtolower($this->name); + return Inflector::humanize(mb_strtolower($this->name)); } } diff --git a/tests/TestCase/Command/EnumCommandTest.php b/tests/TestCase/Command/EnumCommandTest.php index df9d8dd2..8f475b78 100644 --- a/tests/TestCase/Command/EnumCommandTest.php +++ b/tests/TestCase/Command/EnumCommandTest.php @@ -52,4 +52,36 @@ public function testBakeEnum() $result = file_get_contents($this->generatedFile); $this->assertSameAsFile(__FUNCTION__ . '.php', $result); } + + /** + * test baking an enum + * + * @return void + */ + public function testBakeEnumBacked() + { + $this->generatedFile = APP . 'Model/Enum/FooBar.php'; + $this->exec('bake enum FooBar --backed string', ['y']); + + $this->assertExitCode(CommandInterface::CODE_SUCCESS); + $this->assertFileExists($this->generatedFile); + $result = file_get_contents($this->generatedFile); + $this->assertSameAsFile(__FUNCTION__ . '.php', $result); + } + + /** + * test baking an enum + * + * @return void + */ + public function testBakeEnumBackedInt() + { + $this->generatedFile = APP . 'Model/Enum/FooBar.php'; + $this->exec('bake enum FooBar --backed int', ['y']); + + $this->assertExitCode(CommandInterface::CODE_SUCCESS); + $this->assertFileExists($this->generatedFile); + $result = file_get_contents($this->generatedFile); + $this->assertSameAsFile(__FUNCTION__ . '.php', $result); + } } diff --git a/tests/comparisons/Model/testBakeEnum.php b/tests/comparisons/Model/testBakeEnum.php index 85e7e34b..a30e8f39 100644 --- a/tests/comparisons/Model/testBakeEnum.php +++ b/tests/comparisons/Model/testBakeEnum.php @@ -3,16 +3,19 @@ namespace Bake\Test\App\Model\Enum; +use Cake\Database\Type\EnumLabelInterface; +use Cake\Utility\Inflector; + /** * FooBar Enum */ -enum FooBar: int +enum FooBar implements EnumLabelInterface { /** * @return string */ public function label(): string { - return mb_strtolower($this->name); + return Inflector::humanize(mb_strtolower($this->name)); } } diff --git a/tests/comparisons/Model/testBakeEnumBacked.php b/tests/comparisons/Model/testBakeEnumBacked.php new file mode 100644 index 00000000..4b29bbc9 --- /dev/null +++ b/tests/comparisons/Model/testBakeEnumBacked.php @@ -0,0 +1,21 @@ +name)); + } +} diff --git a/tests/comparisons/Model/testBakeEnumBackedInt.php b/tests/comparisons/Model/testBakeEnumBackedInt.php new file mode 100644 index 00000000..41a5514b --- /dev/null +++ b/tests/comparisons/Model/testBakeEnumBackedInt.php @@ -0,0 +1,21 @@ +name)); + } +} From 1f001a56828a39de15f3ef7b68ccfc0e063f5a91 Mon Sep 17 00:00:00 2001 From: mscherer Date: Sat, 23 Dec 2023 15:33:48 +0100 Subject: [PATCH 3/8] Rephrase options help. --- src/Command/EnumCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Command/EnumCommand.php b/src/Command/EnumCommand.php index 34a4c9a1..7ac9a796 100644 --- a/src/Command/EnumCommand.php +++ b/src/Command/EnumCommand.php @@ -90,7 +90,7 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar $parser->setDescription( 'Bake (backed) enums for use in models.' )->addOption('backed', [ - 'help' => 'If using backed enums. Set to `string` or `int`.', + 'help' => 'Valid options are `string` for string columns or `int` for tinyinteger columns.', 'short' => 'b', ]); From 7f827efc58c25c2261f4d5ea9ba8b6139c6af522 Mon Sep 17 00:00:00 2001 From: Mark Scherer Date: Sat, 23 Dec 2023 17:18:46 +0100 Subject: [PATCH 4/8] Update templates/bake/Model/enum.twig Co-authored-by: ADmad --- templates/bake/Model/enum.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/bake/Model/enum.twig b/templates/bake/Model/enum.twig index 00217c18..496780bf 100644 --- a/templates/bake/Model/enum.twig +++ b/templates/bake/Model/enum.twig @@ -29,6 +29,6 @@ enum {{ name }}{{ backed ? ': ' ~ backed : ''}} implements EnumLabelInterface */ public function label(): string { - return Inflector::humanize(mb_strtolower($this->name)); + return Inflector::humanize(Inflector::underscore($this->name)); } } From 3c347af1d4370773f7322ad894adde0d79614c5d Mon Sep 17 00:00:00 2001 From: ADmad Date: Sun, 24 Dec 2023 10:48:20 +0530 Subject: [PATCH 5/8] Fix tests --- tests/comparisons/Model/testBakeEnum.php | 2 +- tests/comparisons/Model/testBakeEnumBacked.php | 2 +- tests/comparisons/Model/testBakeEnumBackedInt.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/comparisons/Model/testBakeEnum.php b/tests/comparisons/Model/testBakeEnum.php index a30e8f39..ec7c61ce 100644 --- a/tests/comparisons/Model/testBakeEnum.php +++ b/tests/comparisons/Model/testBakeEnum.php @@ -16,6 +16,6 @@ enum FooBar implements EnumLabelInterface */ public function label(): string { - return Inflector::humanize(mb_strtolower($this->name)); + return Inflector::humanize(Inflector::underscore($this->name)); } } diff --git a/tests/comparisons/Model/testBakeEnumBacked.php b/tests/comparisons/Model/testBakeEnumBacked.php index 4b29bbc9..41c6faea 100644 --- a/tests/comparisons/Model/testBakeEnumBacked.php +++ b/tests/comparisons/Model/testBakeEnumBacked.php @@ -16,6 +16,6 @@ enum FooBar: string implements EnumLabelInterface */ public function label(): string { - return Inflector::humanize(mb_strtolower($this->name)); + return Inflector::humanize(Inflector::underscore($this->name)); } } diff --git a/tests/comparisons/Model/testBakeEnumBackedInt.php b/tests/comparisons/Model/testBakeEnumBackedInt.php index 41a5514b..c0c0648c 100644 --- a/tests/comparisons/Model/testBakeEnumBackedInt.php +++ b/tests/comparisons/Model/testBakeEnumBackedInt.php @@ -16,6 +16,6 @@ enum FooBar: int implements EnumLabelInterface */ public function label(): string { - return Inflector::humanize(mb_strtolower($this->name)); + return Inflector::humanize(Inflector::underscore($this->name)); } } From 4b9d0e9fa363d64a288f72c0be024a67c0d45286 Mon Sep 17 00:00:00 2001 From: ADmad Date: Sun, 24 Dec 2023 11:03:19 +0530 Subject: [PATCH 6/8] Rename option `backed` to `backing-type` defaulting to `string`. --- src/Command/EnumCommand.php | 16 ++++++-------- templates/bake/Model/enum.twig | 2 +- tests/TestCase/Command/EnumCommandTest.php | 20 ++---------------- tests/comparisons/Model/testBakeEnum.php | 2 +- .../comparisons/Model/testBakeEnumBacked.php | 21 ------------------- 5 files changed, 10 insertions(+), 51 deletions(-) delete mode 100644 tests/comparisons/Model/testBakeEnumBacked.php diff --git a/src/Command/EnumCommand.php b/src/Command/EnumCommand.php index 7ac9a796..fde837e6 100644 --- a/src/Command/EnumCommand.php +++ b/src/Command/EnumCommand.php @@ -66,13 +66,7 @@ public function template(): string public function templateData(Arguments $arguments): array { $data = parent::templateData($arguments); - - $backed = $arguments->getOption('backed'); - if ($backed && !in_array($backed, ['string', 'int'], true)) { - throw new InvalidArgumentException('Backed enums must be of type `string` or `int`'); - } - - $data['backed'] = $backed; + $data['backingType'] = $arguments->getOption('backing-type'); return $data; } @@ -88,9 +82,11 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar $parser = $this->_setCommonOptions($parser); $parser->setDescription( - 'Bake (backed) enums for use in models.' - )->addOption('backed', [ - 'help' => 'Valid options are `string` for string columns or `int` for tinyinteger columns.', + 'Bake enums for use in models.' + )->addOption('backing-type', [ + 'help' => 'The return type for the enum class', + 'default' => 'string', + 'choices' => ['string', 'int'], 'short' => 'b', ]); diff --git a/templates/bake/Model/enum.twig b/templates/bake/Model/enum.twig index 496780bf..fe229b11 100644 --- a/templates/bake/Model/enum.twig +++ b/templates/bake/Model/enum.twig @@ -22,7 +22,7 @@ }) }} {{ DocBlock.classDescription(name, 'Enum', [])|raw }} -enum {{ name }}{{ backed ? ': ' ~ backed : ''}} implements EnumLabelInterface +enum {{ name }}: {{ backingType }} implements EnumLabelInterface { /** * @return string diff --git a/tests/TestCase/Command/EnumCommandTest.php b/tests/TestCase/Command/EnumCommandTest.php index 8f475b78..c6d5bc72 100644 --- a/tests/TestCase/Command/EnumCommandTest.php +++ b/tests/TestCase/Command/EnumCommandTest.php @@ -54,30 +54,14 @@ public function testBakeEnum() } /** - * test baking an enum - * - * @return void - */ - public function testBakeEnumBacked() - { - $this->generatedFile = APP . 'Model/Enum/FooBar.php'; - $this->exec('bake enum FooBar --backed string', ['y']); - - $this->assertExitCode(CommandInterface::CODE_SUCCESS); - $this->assertFileExists($this->generatedFile); - $result = file_get_contents($this->generatedFile); - $this->assertSameAsFile(__FUNCTION__ . '.php', $result); - } - - /** - * test baking an enum + * test baking an enum with int return type * * @return void */ public function testBakeEnumBackedInt() { $this->generatedFile = APP . 'Model/Enum/FooBar.php'; - $this->exec('bake enum FooBar --backed int', ['y']); + $this->exec('bake enum FooBar -b int', ['y']); $this->assertExitCode(CommandInterface::CODE_SUCCESS); $this->assertFileExists($this->generatedFile); diff --git a/tests/comparisons/Model/testBakeEnum.php b/tests/comparisons/Model/testBakeEnum.php index ec7c61ce..41c6faea 100644 --- a/tests/comparisons/Model/testBakeEnum.php +++ b/tests/comparisons/Model/testBakeEnum.php @@ -9,7 +9,7 @@ /** * FooBar Enum */ -enum FooBar implements EnumLabelInterface +enum FooBar: string implements EnumLabelInterface { /** * @return string diff --git a/tests/comparisons/Model/testBakeEnumBacked.php b/tests/comparisons/Model/testBakeEnumBacked.php deleted file mode 100644 index 41c6faea..00000000 --- a/tests/comparisons/Model/testBakeEnumBacked.php +++ /dev/null @@ -1,21 +0,0 @@ -name)); - } -} From 9be993dbc0231b062ad676bf61e0d32b33ddb4fd Mon Sep 17 00:00:00 2001 From: mscherer Date: Sun, 24 Dec 2023 14:38:29 +0100 Subject: [PATCH 7/8] Clarify backed. --- src/Command/EnumCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Command/EnumCommand.php b/src/Command/EnumCommand.php index fde837e6..8385da49 100644 --- a/src/Command/EnumCommand.php +++ b/src/Command/EnumCommand.php @@ -82,9 +82,9 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar $parser = $this->_setCommonOptions($parser); $parser->setDescription( - 'Bake enums for use in models.' + 'Bake backed enums for use in models.' )->addOption('backing-type', [ - 'help' => 'The return type for the enum class', + 'help' => 'The return type for the backed enum class', 'default' => 'string', 'choices' => ['string', 'int'], 'short' => 'b', From 8d042a5ab8b38dbadca612bef532bbbe85b9edc9 Mon Sep 17 00:00:00 2001 From: Mark Scherer Date: Wed, 27 Dec 2023 13:37:45 +0100 Subject: [PATCH 8/8] Make backing type a bool, since it defaults anyway on 1 of 2 options. (#971) * Make backing type a bool, since it defaults anyway on 1 of 2 options. * Use --int / -i as flag. --- src/Command/EnumCommand.php | 12 +++++------- tests/TestCase/Command/EnumCommandTest.php | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Command/EnumCommand.php b/src/Command/EnumCommand.php index 8385da49..2118450e 100644 --- a/src/Command/EnumCommand.php +++ b/src/Command/EnumCommand.php @@ -18,7 +18,6 @@ use Cake\Console\Arguments; use Cake\Console\ConsoleOptionParser; -use InvalidArgumentException; /** * Enum code generator. @@ -66,7 +65,7 @@ public function template(): string public function templateData(Arguments $arguments): array { $data = parent::templateData($arguments); - $data['backingType'] = $arguments->getOption('backing-type'); + $data['backingType'] = $arguments->getOption('int') ? 'int' : 'string'; return $data; } @@ -83,11 +82,10 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar $parser->setDescription( 'Bake backed enums for use in models.' - )->addOption('backing-type', [ - 'help' => 'The return type for the backed enum class', - 'default' => 'string', - 'choices' => ['string', 'int'], - 'short' => 'b', + )->addOption('int', [ + 'help' => 'Using backed enums with int instead of string as return type', + 'boolean' => true, + 'short' => 'i', ]); return $parser; diff --git a/tests/TestCase/Command/EnumCommandTest.php b/tests/TestCase/Command/EnumCommandTest.php index c6d5bc72..678aaf40 100644 --- a/tests/TestCase/Command/EnumCommandTest.php +++ b/tests/TestCase/Command/EnumCommandTest.php @@ -61,7 +61,7 @@ public function testBakeEnum() public function testBakeEnumBackedInt() { $this->generatedFile = APP . 'Model/Enum/FooBar.php'; - $this->exec('bake enum FooBar -b int', ['y']); + $this->exec('bake enum FooBar -i', ['y']); $this->assertExitCode(CommandInterface::CODE_SUCCESS); $this->assertFileExists($this->generatedFile);