From 0b80668f39c05874f16e041230563feba14c809d Mon Sep 17 00:00:00 2001 From: Mark Story Date: Fri, 31 May 2024 23:53:00 -0400 Subject: [PATCH 1/4] Improve enum generation For mapped enums that don't support label() we should not generate a label method call, and expand test coverage. Fixes #989 --- src/View/Helper/BakeHelper.php | 22 ++++++++ templates/bake/Template/index.twig | 5 +- templates/bake/Template/view.twig | 7 +-- .../TestCase/Command/TemplateCommandTest.php | 40 +++++++++++++++ tests/comparisons/Template/testBakeIndex.php | 2 +- .../Template/testBakeIndexHiddenFields.php | 2 +- .../Template/testBakeIndexWithEnum.php | 50 +++++++++++++++++++ .../Template/testBakeIndexWithIndexLimit.php | 2 +- tests/comparisons/Template/testBakeView.php | 2 +- .../comparisons/Template/testBakeViewEnum.php | 44 ++++++++++++++++ .../Template/testBakeViewHiddenFields.php | 2 +- .../Template/testBakeViewWithEnum.php | 0 tests/comparisons/Template/testGetContent.php | 2 +- .../Template/testGetContentAssociations.php | 2 +- .../testGetContentWithRoutingPrefix-view.php | 2 +- 15 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 tests/comparisons/Template/testBakeIndexWithEnum.php create mode 100644 tests/comparisons/Template/testBakeViewEnum.php create mode 100644 tests/comparisons/Template/testBakeViewWithEnum.php diff --git a/src/View/Helper/BakeHelper.php b/src/View/Helper/BakeHelper.php index 52e11dd66..2cdf62209 100644 --- a/src/View/Helper/BakeHelper.php +++ b/src/View/Helper/BakeHelper.php @@ -9,7 +9,9 @@ use Cake\Core\Configure; use Cake\Core\ConventionsTrait; use Cake\Database\Schema\TableSchema; +use Cake\Database\TypeFactory; use Cake\Datasource\SchemaInterface; +use Cake\Database\Type\EnumType; use Cake\ORM\Table; use Cake\Utility\Inflector; use Cake\View\Helper; @@ -281,6 +283,26 @@ public function columnData(string $field, TableSchema $schema): ?array return $schema->getColumn($field); } + /** + * Check if a column is both an enum, and the mapped enum implements `label()` as a method. + * + * @param string $field the field to check + * @param \Cake\Database\Schema\TableSchema $schema The table schema to read from. + * @return bool + */ + public function enumSupportsLabel(string $field, TableSchema $schema): bool + { + $typeName = $schema->getColumnType($field); + if (!str_starts_with($typeName, 'enum-')) { + return false; + } + $type = TypeFactory::build($typeName); + assert($type instanceof EnumType); + $enumClass = $type->getEnumClassName(); + + return method_exists($enumClass, 'label'); + } + /** * Get alias of associated table. * diff --git a/templates/bake/Template/index.twig b/templates/bake/Template/index.twig index 0c6300671..dc3852edc 100644 --- a/templates/bake/Template/index.twig +++ b/templates/bake/Template/index.twig @@ -49,8 +49,9 @@ {% endif %} {% if isKey is not same as(true) %} {% set columnData = Bake.columnData(field, schema) %} +{% set supportsLabel = Bake.enumSupportsLabel(field, schema) %} {% if columnData.type starts with 'enum-' %} - {{ field }} === null ? '' : h(${{ singularVar }}->{{ field }}->label()) ?> + {{ field }} === null ? '' : h(${{ singularVar }}->{{ field }}->{% if supportsLabel %}label(){% else %}value{% endif %}) ?> {% elseif columnData.type not in ['integer', 'float', 'decimal', 'biginteger', 'smallinteger', 'tinyinteger'] %} {{ field }}) ?> {% elseif columnData.null %} @@ -81,4 +82,4 @@

Paginator->counter(__('Page {{ '{{' }}page{{ '}}' }} of {{ '{{' }}pages{{ '}}' }}, showing {{ '{{' }}current{{ '}}' }} record(s) out of {{ '{{' }}count{{ '}}' }} total')) ?>

- + \ No newline at end of file diff --git a/templates/bake/Template/view.twig b/templates/bake/Template/view.twig index 76192e484..4957300ed 100644 --- a/templates/bake/Template/view.twig +++ b/templates/bake/Template/view.twig @@ -81,10 +81,11 @@ {% set columnData = Bake.columnData(field, schema) %} +{% set supportsLabel = Bake.enumSupportsLabel(field, schema) %} {% if columnData.null %} - {{ field }} === null ? '' : h(${{ singularVar }}->{{ field }}->label()) ?> + {{ field }} === null ? '' : h(${{ singularVar }}->{{ field }}->{% if supportsLabel %}label(){% else %}value{% endif %}) ?> {% else %} - {{ field }}->label()) ?> + {{ field }}->{% if supportsLabel %}label(){% else %}value{% endif %}) ?> {% endif %} {% endfor %} @@ -151,4 +152,4 @@ {% endfor %} - + \ No newline at end of file diff --git a/tests/TestCase/Command/TemplateCommandTest.php b/tests/TestCase/Command/TemplateCommandTest.php index 0c3aac315..6ac9b0ec9 100644 --- a/tests/TestCase/Command/TemplateCommandTest.php +++ b/tests/TestCase/Command/TemplateCommandTest.php @@ -17,6 +17,7 @@ namespace Bake\Test\TestCase\Command; use Bake\Command\TemplateCommand; +use Bake\Test\App\Model\Enum\BakeUserStatus; use Bake\Test\App\Model\Table\BakeArticlesTable; use Bake\Test\TestCase\TestCase; use Cake\Console\Arguments; @@ -25,6 +26,7 @@ use Cake\Console\Exception\StopException; use Cake\Core\Configure; use Cake\Core\Plugin; +use Cake\Database\Type\EnumType; use Cake\View\Exception\MissingTemplateException; /** @@ -42,6 +44,7 @@ class TemplateCommandTest extends TestCase 'plugin.Bake.Tags', 'plugin.Bake.ArticlesTags', 'plugin.Bake.Posts', + 'plugin.Bake.Users', 'plugin.Bake.Comments', 'plugin.Bake.BakeArticles', 'plugin.Bake.BakeTemplateAuthors', @@ -449,6 +452,23 @@ public function testBakeView() $this->assertSameAsFile(__FUNCTION__ . '.php', $result); } + /** + * test baking view with enum class + * + * @return void + */ + public function testBakeViewEnum() + { + $this->generatedFile = ROOT . 'templates/BakeUsers/view.php'; + $this->exec('bake template bake_users view'); + + $this->assertExitCode(CommandInterface::CODE_SUCCESS); + $this->assertFileExists($this->generatedFile); + + $result = file_get_contents($this->generatedFile); + $this->assertSameAsFile(__FUNCTION__ . '.php', $result); + } + /** * Test generating view template with hidden fields * @@ -551,6 +571,26 @@ public function testBakeIndexWithIndexLimit() $this->assertSameAsFile(__FUNCTION__ . '.php', $result); } + /** + * test bake template with index enum types + * + * @return void + */ + public function testBakeIndexWithEnum() + { + $table = $this->fetchTable('BakeUsers'); + $table->getSchema()->setColumnType('status', EnumType::from(BakeUserStatus::class)); + + $this->generatedFile = ROOT . 'templates/BakeUsers/index.php'; + $this->exec('bake template bake_users index'); + + $this->assertExitCode(CommandInterface::CODE_SUCCESS); + $this->assertFileExists($this->generatedFile); + + $result = file_get_contents($this->generatedFile); + $this->assertSameAsFile(__FUNCTION__ . '.php', $result); + } + /** * test Bake with plugins * diff --git a/tests/comparisons/Template/testBakeIndex.php b/tests/comparisons/Template/testBakeIndex.php index 3f6ff809a..fe4cc5fa8 100644 --- a/tests/comparisons/Template/testBakeIndex.php +++ b/tests/comparisons/Template/testBakeIndex.php @@ -49,4 +49,4 @@

Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>

- + \ No newline at end of file diff --git a/tests/comparisons/Template/testBakeIndexHiddenFields.php b/tests/comparisons/Template/testBakeIndexHiddenFields.php index 57f008193..74e551f0a 100644 --- a/tests/comparisons/Template/testBakeIndexHiddenFields.php +++ b/tests/comparisons/Template/testBakeIndexHiddenFields.php @@ -39,4 +39,4 @@

Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>

- + \ No newline at end of file diff --git a/tests/comparisons/Template/testBakeIndexWithEnum.php b/tests/comparisons/Template/testBakeIndexWithEnum.php new file mode 100644 index 000000000..b5b497452 --- /dev/null +++ b/tests/comparisons/Template/testBakeIndexWithEnum.php @@ -0,0 +1,50 @@ + $bakeUsers + */ +?> +
+ Html->link(__('New Bake User'), ['action' => 'add'], ['class' => 'button float-right']) ?> +

+
+ + + + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('id') ?>Paginator->sort('username') ?>Paginator->sort('status') ?>Paginator->sort('created') ?>Paginator->sort('updated') ?>
Number->format($bakeUser->id) ?>username) ?>status === null ? '' : h($bakeUser->status->label()) ?>created) ?>updated) ?> + Html->link(__('View'), ['action' => 'view', $bakeUser->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $bakeUser->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $bakeUser->id], ['confirm' => __('Are you sure you want to delete # {0}?', $bakeUser->id)]) ?> +
+
+
+
    + Paginator->first('<< ' . __('first')) ?> + Paginator->prev('< ' . __('previous')) ?> + Paginator->numbers() ?> + Paginator->next(__('next') . ' >') ?> + Paginator->last(__('last') . ' >>') ?> +
+

Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>

+
+
\ No newline at end of file diff --git a/tests/comparisons/Template/testBakeIndexWithIndexLimit.php b/tests/comparisons/Template/testBakeIndexWithIndexLimit.php index 34b8f8caa..fd6a3bf69 100644 --- a/tests/comparisons/Template/testBakeIndexWithIndexLimit.php +++ b/tests/comparisons/Template/testBakeIndexWithIndexLimit.php @@ -43,4 +43,4 @@

Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>

- + \ No newline at end of file diff --git a/tests/comparisons/Template/testBakeView.php b/tests/comparisons/Template/testBakeView.php index 7e37823b1..6a84c7623 100644 --- a/tests/comparisons/Template/testBakeView.php +++ b/tests/comparisons/Template/testBakeView.php @@ -94,4 +94,4 @@ - + \ No newline at end of file diff --git a/tests/comparisons/Template/testBakeViewEnum.php b/tests/comparisons/Template/testBakeViewEnum.php new file mode 100644 index 000000000..49391e452 --- /dev/null +++ b/tests/comparisons/Template/testBakeViewEnum.php @@ -0,0 +1,44 @@ + +
+ +
+
+

id) ?>

+ + + + + + + + + + + + + + + + + + + + + +
username) ?>
Number->format($bakeUser->id) ?>
status === null ? '' : $this->Number->format($bakeUser->status) ?>
created) ?>
updated) ?>
+
+
+
\ No newline at end of file diff --git a/tests/comparisons/Template/testBakeViewHiddenFields.php b/tests/comparisons/Template/testBakeViewHiddenFields.php index add7cb221..441738d84 100644 --- a/tests/comparisons/Template/testBakeViewHiddenFields.php +++ b/tests/comparisons/Template/testBakeViewHiddenFields.php @@ -25,4 +25,4 @@ - + \ No newline at end of file diff --git a/tests/comparisons/Template/testBakeViewWithEnum.php b/tests/comparisons/Template/testBakeViewWithEnum.php new file mode 100644 index 000000000..e69de29bb diff --git a/tests/comparisons/Template/testGetContent.php b/tests/comparisons/Template/testGetContent.php index 0b4545134..f9b363f71 100644 --- a/tests/comparisons/Template/testGetContent.php +++ b/tests/comparisons/Template/testGetContent.php @@ -33,4 +33,4 @@ - + \ No newline at end of file diff --git a/tests/comparisons/Template/testGetContentAssociations.php b/tests/comparisons/Template/testGetContentAssociations.php index a9cdb9ad7..689c58ca8 100644 --- a/tests/comparisons/Template/testGetContentAssociations.php +++ b/tests/comparisons/Template/testGetContentAssociations.php @@ -33,4 +33,4 @@ - + \ No newline at end of file diff --git a/tests/comparisons/Template/testGetContentWithRoutingPrefix-view.php b/tests/comparisons/Template/testGetContentWithRoutingPrefix-view.php index 2521bf4b7..6d3a80422 100644 --- a/tests/comparisons/Template/testGetContentWithRoutingPrefix-view.php +++ b/tests/comparisons/Template/testGetContentWithRoutingPrefix-view.php @@ -35,4 +35,4 @@ - + \ No newline at end of file From f20e02a5cf291a748f172d8258924ec3fd3c2c22 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 1 Jun 2024 00:11:42 -0400 Subject: [PATCH 2/4] Expand coverage --- .../TestCase/Command/TemplateCommandTest.php | 46 ++++++++++++++++++- .../Template/testBakeIndexWithEnumNoLabel.php | 0 .../testBakeIndexWithEnumWithLabel.php | 0 .../Template/testBakeViewEnumNoLabel.php | 0 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/comparisons/Template/testBakeIndexWithEnumNoLabel.php create mode 100644 tests/comparisons/Template/testBakeIndexWithEnumWithLabel.php create mode 100644 tests/comparisons/Template/testBakeViewEnumNoLabel.php diff --git a/tests/TestCase/Command/TemplateCommandTest.php b/tests/TestCase/Command/TemplateCommandTest.php index 6ac9b0ec9..715b80fe6 100644 --- a/tests/TestCase/Command/TemplateCommandTest.php +++ b/tests/TestCase/Command/TemplateCommandTest.php @@ -17,6 +17,7 @@ namespace Bake\Test\TestCase\Command; use Bake\Command\TemplateCommand; +use Bake\Test\App\Model\Enum\ArticleStatus; use Bake\Test\App\Model\Enum\BakeUserStatus; use Bake\Test\App\Model\Table\BakeArticlesTable; use Bake\Test\TestCase\TestCase; @@ -459,6 +460,9 @@ public function testBakeView() */ public function testBakeViewEnum() { + $table = $this->fetchTable('BakeUsers'); + $table->getSchema()->setColumnType('status', EnumType::from(BakeUserStatus::class)); + $this->generatedFile = ROOT . 'templates/BakeUsers/view.php'; $this->exec('bake template bake_users view'); @@ -469,6 +473,26 @@ public function testBakeViewEnum() $this->assertSameAsFile(__FUNCTION__ . '.php', $result); } + /** + * test baking view with enum class + * + * @return void + */ + public function testBakeViewEnumNoLabel() + { + $table = $this->fetchTable('Articles'); + $table->getSchema()->setColumnType('status', EnumType::from(ArticleStatus::class)); + + $this->generatedFile = ROOT . 'templates/Articles/view.php'; + $this->exec('bake template articles view'); + + $this->assertExitCode(CommandInterface::CODE_SUCCESS); + $this->assertFileExists($this->generatedFile); + + $result = file_get_contents($this->generatedFile); + $this->assertSameAsFile(__FUNCTION__ . '.php', $result); + } + /** * Test generating view template with hidden fields * @@ -576,7 +600,7 @@ public function testBakeIndexWithIndexLimit() * * @return void */ - public function testBakeIndexWithEnum() + public function testBakeIndexWithEnumWithLabel() { $table = $this->fetchTable('BakeUsers'); $table->getSchema()->setColumnType('status', EnumType::from(BakeUserStatus::class)); @@ -591,6 +615,26 @@ public function testBakeIndexWithEnum() $this->assertSameAsFile(__FUNCTION__ . '.php', $result); } + /** + * test bake template with index enum types + * + * @return void + */ + public function testBakeIndexWithEnumNoLabel() + { + $table = $this->fetchTable('Articles'); + $table->getSchema()->setColumnType('status', EnumType::from(ArticleStatus::class)); + + $this->generatedFile = ROOT . 'templates/Articles/index.php'; + $this->exec('bake template articles index'); + + $this->assertExitCode(CommandInterface::CODE_SUCCESS); + $this->assertFileExists($this->generatedFile); + + $result = file_get_contents($this->generatedFile); + $this->assertSameAsFile(__FUNCTION__ . '.php', $result); + } + /** * test Bake with plugins * diff --git a/tests/comparisons/Template/testBakeIndexWithEnumNoLabel.php b/tests/comparisons/Template/testBakeIndexWithEnumNoLabel.php new file mode 100644 index 000000000..e69de29bb diff --git a/tests/comparisons/Template/testBakeIndexWithEnumWithLabel.php b/tests/comparisons/Template/testBakeIndexWithEnumWithLabel.php new file mode 100644 index 000000000..e69de29bb diff --git a/tests/comparisons/Template/testBakeViewEnumNoLabel.php b/tests/comparisons/Template/testBakeViewEnumNoLabel.php new file mode 100644 index 000000000..e69de29bb From 70e0b3462ff18267792e6463a545c88f6610f3c1 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 1 Jun 2024 00:13:57 -0400 Subject: [PATCH 3/4] Update fixtures, fix formatting --- src/View/Helper/BakeHelper.php | 2 +- .../Template/testBakeIndexWithEnumNoLabel.php | 48 ++++++++++++ .../testBakeIndexWithEnumWithLabel.php | 50 +++++++++++++ .../comparisons/Template/testBakeViewEnum.php | 2 +- .../Template/testBakeViewEnumNoLabel.php | 75 +++++++++++++++++++ 5 files changed, 175 insertions(+), 2 deletions(-) diff --git a/src/View/Helper/BakeHelper.php b/src/View/Helper/BakeHelper.php index 2cdf62209..431405b32 100644 --- a/src/View/Helper/BakeHelper.php +++ b/src/View/Helper/BakeHelper.php @@ -9,9 +9,9 @@ use Cake\Core\Configure; use Cake\Core\ConventionsTrait; use Cake\Database\Schema\TableSchema; +use Cake\Database\Type\EnumType; use Cake\Database\TypeFactory; use Cake\Datasource\SchemaInterface; -use Cake\Database\Type\EnumType; use Cake\ORM\Table; use Cake\Utility\Inflector; use Cake\View\Helper; diff --git a/tests/comparisons/Template/testBakeIndexWithEnumNoLabel.php b/tests/comparisons/Template/testBakeIndexWithEnumNoLabel.php index e69de29bb..8f3ee6d15 100644 --- a/tests/comparisons/Template/testBakeIndexWithEnumNoLabel.php +++ b/tests/comparisons/Template/testBakeIndexWithEnumNoLabel.php @@ -0,0 +1,48 @@ + $articles + */ +?> +
+ Html->link(__('New Article'), ['action' => 'add'], ['class' => 'button float-right']) ?> +

+
+ + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('id') ?>Paginator->sort('author_id') ?>Paginator->sort('title') ?>Paginator->sort('published') ?>
Number->format($article->id) ?>hasValue('author') ? $this->Html->link($article->author->name, ['controller' => 'Authors', 'action' => 'view', $article->author->id]) : '' ?>title) ?>published === null ? '' : h($article->published->value) ?> + Html->link(__('View'), ['action' => 'view', $article->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $article->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $article->id], ['confirm' => __('Are you sure you want to delete # {0}?', $article->id)]) ?> +
+
+
+
    + Paginator->first('<< ' . __('first')) ?> + Paginator->prev('< ' . __('previous')) ?> + Paginator->numbers() ?> + Paginator->next(__('next') . ' >') ?> + Paginator->last(__('last') . ' >>') ?> +
+

Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>

+
+
\ No newline at end of file diff --git a/tests/comparisons/Template/testBakeIndexWithEnumWithLabel.php b/tests/comparisons/Template/testBakeIndexWithEnumWithLabel.php index e69de29bb..b5b497452 100644 --- a/tests/comparisons/Template/testBakeIndexWithEnumWithLabel.php +++ b/tests/comparisons/Template/testBakeIndexWithEnumWithLabel.php @@ -0,0 +1,50 @@ + $bakeUsers + */ +?> +
+ Html->link(__('New Bake User'), ['action' => 'add'], ['class' => 'button float-right']) ?> +

+
+ + + + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('id') ?>Paginator->sort('username') ?>Paginator->sort('status') ?>Paginator->sort('created') ?>Paginator->sort('updated') ?>
Number->format($bakeUser->id) ?>username) ?>status === null ? '' : h($bakeUser->status->label()) ?>created) ?>updated) ?> + Html->link(__('View'), ['action' => 'view', $bakeUser->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $bakeUser->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $bakeUser->id], ['confirm' => __('Are you sure you want to delete # {0}?', $bakeUser->id)]) ?> +
+
+
+
    + Paginator->first('<< ' . __('first')) ?> + Paginator->prev('< ' . __('previous')) ?> + Paginator->numbers() ?> + Paginator->next(__('next') . ' >') ?> + Paginator->last(__('last') . ' >>') ?> +
+

Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>

+
+
\ No newline at end of file diff --git a/tests/comparisons/Template/testBakeViewEnum.php b/tests/comparisons/Template/testBakeViewEnum.php index 49391e452..4cae270bd 100644 --- a/tests/comparisons/Template/testBakeViewEnum.php +++ b/tests/comparisons/Template/testBakeViewEnum.php @@ -28,7 +28,7 @@ - status === null ? '' : $this->Number->format($bakeUser->status) ?> + status === null ? '' : h($bakeUser->status->label()) ?> diff --git a/tests/comparisons/Template/testBakeViewEnumNoLabel.php b/tests/comparisons/Template/testBakeViewEnumNoLabel.php index e69de29bb..e5e0fd4b9 100644 --- a/tests/comparisons/Template/testBakeViewEnumNoLabel.php +++ b/tests/comparisons/Template/testBakeViewEnumNoLabel.php @@ -0,0 +1,75 @@ + +
+ +
+
+

title) ?>

+ + + + + + + + + + + + + + + + + +
hasValue('author') ? $this->Html->link($article->author->name, ['controller' => 'Authors', 'action' => 'view', $article->author->id]) : '' ?>
title) ?>
Number->format($article->id) ?>
published === null ? '' : h($article->published->value) ?>
+
+ +
+ Text->autoParagraph(h($article->body)); ?> +
+
+ +
+
+
\ No newline at end of file From 357076f61aae127c8ed278c38d2aae6280c40b3c Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 1 Jun 2024 23:08:36 -0400 Subject: [PATCH 4/4] Fix tests --- tests/TestCase/Command/TemplateCommandTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/TestCase/Command/TemplateCommandTest.php b/tests/TestCase/Command/TemplateCommandTest.php index 715b80fe6..7c0e47b0c 100644 --- a/tests/TestCase/Command/TemplateCommandTest.php +++ b/tests/TestCase/Command/TemplateCommandTest.php @@ -461,6 +461,7 @@ public function testBakeView() public function testBakeViewEnum() { $table = $this->fetchTable('BakeUsers'); + $table->associations()->removeAll(); $table->getSchema()->setColumnType('status', EnumType::from(BakeUserStatus::class)); $this->generatedFile = ROOT . 'templates/BakeUsers/view.php';