Skip to content

Commit

Permalink
Merge pull request #976 from cakephp/3.next
Browse files Browse the repository at this point in the history
next minor release 3.1.0
  • Loading branch information
markstory committed Jan 30, 2024
2 parents ba5edc2 + 078ca3c commit d5ae87b
Show file tree
Hide file tree
Showing 29 changed files with 1,104 additions and 42 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Expand Up @@ -6,6 +6,7 @@ on:
- 2.x
- 2.next
- 3.x
- 3.next
pull_request:
branches:
- '*'
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -22,7 +22,7 @@
"require": {
"php": ">=8.1",
"brick/varexporter": "^0.4.0",
"cakephp/cakephp": "^5.0.0",
"cakephp/cakephp": "^5.0.3",
"cakephp/twig-view": "^2.0.0",
"nikic/php-parser": "^4.13.2 || ^5.0.0"
},
Expand Down
2 changes: 2 additions & 0 deletions docs/en/usage.rst
Expand Up @@ -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
Expand Down
173 changes: 173 additions & 0 deletions src/Command/EnumCommand.php
@@ -0,0 +1,173 @@
<?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\Command;

use Bake\Utility\Model\EnumParser;
use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
use Cake\Console\ConsoleOptionParser;
use Cake\Utility\Inflector;
use InvalidArgumentException;

/**
* Enum code generator.
*/
class EnumCommand extends SimpleBakeCommand
{
/**
* Task name used in path generation.
*
* @var string
*/
public string $pathFragment = 'Model/Enum/';

/**
* @inheritDoc
*/
public function name(): string
{
return 'enum';
}

/**
* @inheritDoc
*/
public function fileName(string $name): string
{
return $name . '.php';
}

/**
* @inheritDoc
*/
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<string, mixed>
*/
public function templateData(Arguments $arguments): array
{
$cases = EnumParser::parseCases($arguments->getArgument('cases'), (bool)$arguments->getOption('int'));
$isOfTypeInt = $this->isOfTypeInt($cases);
$backingType = $isOfTypeInt ? 'int' : 'string';
if ($arguments->getOption('int')) {
if ($cases && !$isOfTypeInt) {
throw new InvalidArgumentException('Cases do not match requested `int` backing type.');
}

$backingType = 'int';
}

$data = parent::templateData($arguments);
$data['backingType'] = $backingType;
$data['cases'] = $this->formatCases($cases);

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.'
)->addArgument('name', [
'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 `foo:0,bar:1` for int type.',
])->addOption('int', [
'help' => 'Using backed enums with int instead of string as return type.',
'boolean' => true,
'short' => 'i',
]);

return $parser;
}

/**
* @param array<string, int|string> $definition
* @return bool
*/
protected function isOfTypeInt(array $definition): bool
{
if (!$definition) {
return false;
}

foreach ($definition as $value) {
if (!is_int($value)) {
return false;
}
}

return true;
}

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

return $formatted;
}

/**
* Generate a class stub
*
* @param string $name The class name
* @param \Cake\Console\Arguments $args The console arguments
* @param \Cake\Console\ConsoleIo $io The console io
* @return void
*/
protected function bake(string $name, Arguments $args, ConsoleIo $io): void
{
parent::bake($name, $args, $io);

$path = $this->getPath($args);
$filename = $path . $name . '.php';

// Work around composer caching that classes/files do not exist.
// Check for the file as it might not exist in tests.
if (file_exists($filename)) {
require_once $filename;
}
}
}

0 comments on commit d5ae87b

Please sign in to comment.