Skip to content

Commit

Permalink
Switch key/value, use CamelCase
Browse files Browse the repository at this point in the history
  • Loading branch information
dereuromark committed Dec 31, 2023
1 parent 36afd65 commit f5a3766
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 47 deletions.
51 changes: 12 additions & 39 deletions src/Command/EnumCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
namespace Bake\Command;

use Bake\Utility\Model\EnumParser;
use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
use Cake\Console\ConsoleOptionParser;
Expand Down Expand Up @@ -67,7 +68,7 @@ public function template(): string
*/
public function templateData(Arguments $arguments): array
{
$cases = $this->parseCases($arguments->getArgument('cases'), (bool)$arguments->getOption('int'));
$cases = EnumParser::parseCases($arguments->getArgument('cases'), (bool)$arguments->getOption('int'));
$isOfTypeInt = $this->isOfTypeInt($cases);
$backingType = $isOfTypeInt ? 'int' : 'string';
if ($arguments->getOption('int')) {
Expand Down Expand Up @@ -101,7 +102,7 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar
'help' => 'Name of the enum to bake. You can use Plugin.name to bake plugin enums.',
'required' => true,
])->addArgument('cases', [
'help' => 'List of either `one,two` for string or `0:foo,1:bar` for int type.',
'help' => 'List of either `one,two` for string or `foo:0,bar:1` for int type.',
])->addOption('int', [
'help' => 'Using backed enums with int instead of string as return type.',
'boolean' => true,
Expand All @@ -112,35 +113,7 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar
}

/**
* @param string|null $casesString
* @return array<int|string, string>
*/
protected function parseCases(?string $casesString, bool $int): array
{
if ($casesString === null) {
return [];
}

$enumCases = explode(',', $casesString);

$definition = [];
foreach ($enumCases as $k => $enumCase) {
$key = $value = trim($enumCase);
if (str_contains($key, ':')) {
$value = trim(mb_substr($key, strpos($key, ':') + 1));
$key = mb_substr($key, 0, strpos($key, ':'));
} elseif ($int) {
$key = $k;
}

$definition[$key] = $value;
}

return $definition;
}

/**
* @param array<int|string, string> $definition
* @param array<string, int|string> $definition
* @return bool
*/
protected function isOfTypeInt(array $definition): bool
Expand All @@ -149,8 +122,8 @@ protected function isOfTypeInt(array $definition): bool
return false;
}

foreach ($definition as $key => $value) {
if (!is_int($key)) {
foreach ($definition as $value) {
if (!is_int($value)) {
return false;
}
}
Expand All @@ -159,18 +132,18 @@ protected function isOfTypeInt(array $definition): bool
}

/**
* @param array<int|string, string> $cases
* @param array<string, int|string> $cases
* @return array<string>
*/
protected function formatCases(array $cases): array
{
$formatted = [];
foreach ($cases as $case => $alias) {
$alias = mb_strtoupper(Inflector::underscore($alias));
if (is_string($case)) {
$case = '\'' . $case . '\'';
foreach ($cases as $case => $value) {
$case = Inflector::camelize(Inflector::underscore($case));
if (is_string($value)) {
$value = '\'' . $value . '\'';
}
$formatted[] = 'case ' . $alias . ' = ' . $case . ';';
$formatted[] = 'case ' . $case . ' = ' . $value . ';';
}

return $formatted;
Expand Down
6 changes: 4 additions & 2 deletions src/Command/ModelCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
namespace Bake\Command;

use Bake\CodeGen\FileBuilder;
use Bake\Utility\Model\EnumParser;
use Bake\Utility\TableScanner;
use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
Expand Down Expand Up @@ -1473,8 +1474,9 @@ protected function getEnumDefinitions(TableSchemaInterface $schema): array
continue;
}

$enumsDefinitionString = mb_substr($columnSchema['comment'], strpos($columnSchema['comment'], '[enum]') + 6);
$enumsDefinition = $this->parseEnumsDefinition($enumsDefinitionString);
$enumsDefinitionString = trim(mb_substr($columnSchema['comment'], strpos($columnSchema['comment'], '[enum]') + 6));
$isInt = in_array($columnSchema['type'], ['integer', 'tinyinteger', 'smallinteger', true]);
$enumsDefinition = EnumParser::parseCases($enumsDefinitionString, $isInt);
if (!$enumsDefinition) {
continue;

Check warning on line 1481 in src/Command/ModelCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/ModelCommand.php#L1477-L1481

Added lines #L1477 - L1481 were not covered by tests
}
Expand Down
36 changes: 36 additions & 0 deletions src/Utility/Model/EnumParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);

namespace Bake\Utility\Model;

enum EnumParser
{
/**
* @param string|null $casesString
* @param bool $int
* @return array<string, int|string>
*/
public static function parseCases(?string $casesString, bool $int): array
{
if ($casesString === null || $casesString === '') {
return [];
}

$enumCases = explode(',', $casesString);

$definition = [];
foreach ($enumCases as $k => $enumCase) {
$case = $value = trim($enumCase);
if (str_contains($case, ':')) {
$value = trim(mb_substr($case, strpos($case, ':') + 1));
$case = mb_substr($case, 0, strpos($case, ':'));
} elseif ($int) {
$value = $k;
}

$definition[$case] = $int ? (int)$value : $value;
}

return $definition;
}
}
2 changes: 1 addition & 1 deletion templates/bake/Model/enum.twig
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ enum {{ name }}: {{ backingType }} implements EnumLabelInterface
*/
public function label(): string
{
return Inflector::humanize(mb_strtolower($this->name));
return Inflector::humanize(Inflector::underscore($this->name));
}
}
32 changes: 32 additions & 0 deletions tests/TestCase/Command/EnumCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,36 @@ public function testBakeEnumBackedInt()
$result = file_get_contents($this->generatedFile);
$this->assertSameAsFile(__FUNCTION__ . '.php', $result);
}

/**
* test baking an enum with string return type and cases
*
* @return void
*/
public function testBakeEnumBackedWithCases()
{
$this->generatedFile = APP . 'Model/Enum/FooBar.php';
$this->exec('bake enum FooBar foo,bar:b,bar_baz', ['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 with string return type and cases
*
* @return void
*/
public function testBakeEnumBackedIntWithCases()
{
$this->generatedFile = APP . 'Model/Enum/FooBar.php';
$this->exec('bake enum FooBar foo,bar,bar_baz:9 -i', ['y']);

$this->assertExitCode(CommandInterface::CODE_SUCCESS);
$this->assertFileExists($this->generatedFile);
$result = file_get_contents($this->generatedFile);
$this->assertSameAsFile(__FUNCTION__ . '.php', $result);
}
}
47 changes: 47 additions & 0 deletions tests/TestCase/Utility/Model/EnumParserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);

/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 3.1.0
* @license https://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Bake\Test\TestCase\Utility\Model;

use Bake\Utility\Model\EnumParser;
use Cake\TestSuite\TestCase;

/**
* BakeViewTest class
*/
class EnumParserTest extends TestCase
{
/**
* @return void
*/
public function testParseCases(): void
{
$cases = EnumParser::parseCases('', false);
$this->assertSame([], $cases);

$cases = EnumParser::parseCases('foo, bar', false);
$this->assertSame(['foo' => 'foo', 'bar' => 'bar'], $cases);

$cases = EnumParser::parseCases('foo:f, bar:b', false);
$this->assertSame(['foo' => 'f', 'bar' => 'b'], $cases);

$cases = EnumParser::parseCases('foo:0, bar:1', true);
$this->assertSame(['foo' => 0, 'bar' => 1], $cases);

$cases = EnumParser::parseCases('foo, bar', true);
$this->assertSame(['foo' => 0, 'bar' => 1], $cases);
}
}
2 changes: 1 addition & 1 deletion tests/comparisons/Model/testBakeEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
2 changes: 1 addition & 1 deletion tests/comparisons/Model/testBakeEnumBackedInt.php
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
25 changes: 25 additions & 0 deletions tests/comparisons/Model/testBakeEnumBackedIntWithCases.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace Bake\Test\App\Model\Enum;

use Cake\Database\Type\EnumLabelInterface;
use Cake\Utility\Inflector;

/**
* FooBar Enum
*/
enum FooBar: int implements EnumLabelInterface
{
case Foo = 0;
case Bar = 1;
case BarBaz = 9;

/**
* @return string
*/
public function label(): string
{
return Inflector::humanize(Inflector::underscore($this->name));
}
}
25 changes: 25 additions & 0 deletions tests/comparisons/Model/testBakeEnumBackedWithCases.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace Bake\Test\App\Model\Enum;

use Cake\Database\Type\EnumLabelInterface;
use Cake\Utility\Inflector;

/**
* FooBar Enum
*/
enum FooBar: string implements EnumLabelInterface
{
case Foo = 'foo';
case Bar = 'b';
case BarBaz = 'bar_baz';

/**
* @return string
*/
public function label(): string
{
return Inflector::humanize(Inflector::underscore($this->name));
}
}
6 changes: 3 additions & 3 deletions tests/test_app/App/Model/Enum/BakeUserStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@

enum BakeUserStatus: int implements EnumLabelInterface
{
case INACTIVE = 0;
case ACTIVE = 1;
case Inactive = 0;
case Active = 1;

/**
* @return string
*/
public function label(): string
{
return Inflector::humanize(mb_strtolower($this->name));
return Inflector::humanize(Inflector::underscore($this->name));
}
}

0 comments on commit f5a3766

Please sign in to comment.