Skip to content

Commit

Permalink
Merge pull request cakephp#17400 from cakephp/5.x-enum-interface
Browse files Browse the repository at this point in the history
Add Interface for enum labels.
  • Loading branch information
markstory authored Nov 3, 2023
2 parents 3b8a0ae + ec5db95 commit cbb5022
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 1 deletion.
31 changes: 31 additions & 0 deletions src/Database/Type/EnumLabelInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?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 5.0.3
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Database\Type;

/**
* An interface used to clarify that an enum has a label() method instead of having to use
* `name` property.
*/
interface EnumLabelInterface
{
/**
* Label to return as string.
*
* @return string
*/
public function label(): string;
}
4 changes: 3 additions & 1 deletion src/View/Helper/FormHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use BackedEnum;
use Cake\Core\Configure;
use Cake\Core\Exception\CakeException;
use Cake\Database\Type\EnumLabelInterface;
use Cake\Database\Type\EnumType;
use Cake\Database\TypeFactory;
use Cake\Form\FormProtector;
Expand Down Expand Up @@ -1358,7 +1359,8 @@ protected function enumOptions(string $enumClass): array
$values = [];
/** @var \BackedEnum $case */
foreach ($enumClass::cases() as $case) {
$values[$case->value] = method_exists($case, 'label') ? $case->label() : $case->name;
$hasLabel = $case instanceof EnumLabelInterface || method_exists($case, 'label');
$values[$case->value] = $hasLabel ? $case->label() : $case->name;
}

return $values;
Expand Down
26 changes: 26 additions & 0 deletions tests/TestCase/View/Helper/FormHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
use TestApp\Model\Entity\Article;
use TestApp\Model\Enum\ArticleStatus;
use TestApp\Model\Enum\ArticleStatusLabel;
use TestApp\Model\Enum\ArticleStatusLabelInterface;
use TestApp\Model\Table\ContactsTable;
use TestApp\Model\Table\ValidateUsersTable;
use TestApp\View\Form\StubContext;
Expand Down Expand Up @@ -3671,6 +3672,31 @@ public function testControlSelectType(): void
'/div',
];
$this->assertHtml($expected, $result);

$articlesTable->getSchema()->setColumnType(
'published',
EnumType::from(ArticleStatusLabelInterface::class)
);

$article = $articlesTable->newEmptyEntity();
$this->Form->create($article);
$result = $this->Form->control('published');
$expected = [
'div' => ['class' => 'input select'],
'label' => ['for' => 'published'],
'Published',
'/label',
'select' => ['name' => 'published', 'id' => 'published'],
['option' => ['value' => 'Y']],
'Is published',
'/option',
['option' => ['value' => 'N', 'selected' => 'selected']],
'Is unpublished',
'/option',
'/select',
'/div',
];
$this->assertHtml($expected, $result);
}

/**
Expand Down
31 changes: 31 additions & 0 deletions tests/test_app/TestApp/Model/Enum/ArticleStatusLabelInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?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
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @since 5.0.3
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace TestApp\Model\Enum;

use Cake\Database\Type\EnumLabelInterface;

enum ArticleStatusLabelInterface: string implements EnumLabelInterface
{
case PUBLISHED = 'Y';
case UNPUBLISHED = 'N';

/**
* @return string
*/
public function label(): string
{
return 'Is ' . strtolower($this->name);
}
}

0 comments on commit cbb5022

Please sign in to comment.