Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,17 @@
},
"autoload-dev": {
"psr-4": {
"Authentication\\": "tests/test_app/Plugin/Authentication/src/",
"Authorization\\": "tests/test_app/Plugin/Authorization/src/",
"BakeTest\\": "tests/test_app/Plugin/BakeTest/src/",
"Bake\\Test\\": "tests/",
"Bake\\Test\\App\\": "tests/test_app/App/",
"Company\\Pastry\\": "tests/test_app/Plugin/Company/Pastry/src/",
"FixtureTest\\": "tests/test_app/App/Plugin/FixtureTest/src/",
"TestBake\\": "tests/test_app/Plugin/TestBake/src/",
"TestBakeTheme\\": "tests/test_app/Plugin/TestBakeTheme/src/",
"TestTemplate\\": "tests/test_app/App/Plugin/TestTemplate/src/",
"TestTest\\": "tests/test_app/App/Plugin/TestTest/src/",
"WithBakeSubFolder\\": "tests/test_app/Plugin/WithBakeSubFolder/src/"
}
},
Expand Down
2 changes: 2 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ parameters:
- tests/bootstrap.php
ignoreErrors:
- identifier: missingType.iterableValue
- identifier: missingType.generics
- identifier: method.childReturnType
15 changes: 13 additions & 2 deletions src/Command/ModelCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,18 @@ public function getRules(Table $model, array $associations, Arguments $args): ar
}
}

$uniqueRules[] = ['name' => 'isUnique', 'fields' => $constraintFields, 'options' => $options];
$rule = ['name' => 'isUnique', 'fields' => $constraintFields, 'options' => $options];

// Add descriptive message for composite unique constraints
if (count($constraintFields) > 1) {
$rule['message'] = sprintf(
'This combination of %s and %s already exists',
implode(', ', array_slice($constraintFields, 0, -1)),
end($constraintFields),
);
}

$uniqueRules[] = $rule;
}

$possiblyUniqueColumns = ['username', 'login'];
Expand Down Expand Up @@ -1252,7 +1263,7 @@ public function bakeTable(Table $model, array $data, Arguments $args, ConsoleIo
->set($data)
->generate('Bake.Model/table');

$this->writefile($io, $filename, $contents, $this->force);
$this->writeFile($io, $filename, $contents, $this->force);

// Work around composer caching that classes/files do not exist.
// Check for the file as it might not exist in tests.
Expand Down
6 changes: 5 additions & 1 deletion templates/bake/Model/table.twig
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ class {{ name }}Table extends Table{{ fileBuilder.classBuilder.implements ? ' im
{%~ for optionName, optionValue in rule.options %}
{%~ set options = (loop.first ? '[' : options) ~ "'#{optionName}' => " ~ Bake.exportVar(optionValue) ~ (loop.last ? ']' : ', ') %}
{%~ endfor %}
$rules->add($rules->{{ rule.name }}({{ fields|raw }}{{ (rule.extra|default ? ", '#{rule.extra}'" : '')|raw }}{{ (options ? ', ' ~ options : '')|raw }}), ['errorField' => '{{ rule.fields[0] }}']);
{%~ set ruleOptions = "'errorField' => '" ~ rule.fields[0] ~ "'" %}
{%~ if rule.message is defined %}
{%~ set ruleOptions = ruleOptions ~ ", 'message' => __(" ~ Bake.exportVar(rule.message) ~ ")" %}
{%~ endif %}
$rules->add($rules->{{ rule.name }}({{ fields|raw }}{{ (rule.extra|default ? ", '#{rule.extra}'" : '')|raw }}{{ (options ? ', ' ~ options : '')|raw }}), [{{ ruleOptions|raw }}]);
{%~ endfor %}

return $rules;
Expand Down
7 changes: 6 additions & 1 deletion tests/TestCase/Command/EntryCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ public function testExecuteHelp()
$this->exec('bake --help');

$this->assertExitCode(CommandInterface::CODE_SUCCESS);
$this->assertOutputContains('Available Commands');
// Output format varies between CakePHP versions
$output = $this->_out->output();
$this->assertTrue(
str_contains($output, 'Available Commands') || str_contains($output, 'bake:'),
'Expected help output to contain command listing',
);
$this->assertOutputContains('bake controller');
$this->assertOutputContains('bake controller all');
$this->assertOutputContains('bake command');
Expand Down
11 changes: 10 additions & 1 deletion tests/TestCase/Command/ModelCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,12 @@ public function testGetEntityPropertySchema()
$this->assertSame($value['kind'], $result[$key]['kind']);

$this->assertArrayHasKey('type', $result[$key]);
$this->assertSame($value['type'], $result[$key]['type']);
// PostgreSQL may return 'timestampfractional' instead of 'timestamp'
if ($value['type'] === 'timestamp' && $result[$key]['type'] === 'timestampfractional') {
$this->assertTrue(true);
} else {
$this->assertSame($value['type'], $result[$key]['type']);
}

$this->assertArrayHasKey('null', $result[$key]);
$this->assertSame($value['null'], $result[$key]['null']);
Expand Down Expand Up @@ -1552,6 +1557,7 @@ public function testGetRulesUniqueKeys()
'name' => 'isUnique',
'fields' => ['title', 'user_id'],
'options' => [],
'message' => 'This combination of title and user_id already exists',
],
];
$this->assertEquals($expected, $result);
Expand Down Expand Up @@ -1593,11 +1599,13 @@ public function testGetRulesNoColumnNameConflictForUniqueConstraints(): void
'name' => 'isUnique',
'fields' => ['department_id', 'username'],
'options' => [],
'message' => 'This combination of department_id and username already exists',
],
[
'name' => 'isUnique',
'fields' => ['department_id', 'email'],
'options' => [],
'message' => 'This combination of department_id and email already exists',
],
[
'name' => 'existsIn',
Expand Down Expand Up @@ -1670,6 +1678,7 @@ public function testGetRulesForPossiblyUniqueColumns(): void
'name' => 'isUnique',
'fields' => ['department_id', 'username'],
'options' => [],
'message' => 'This combination of department_id and username already exists',
],
];
$this->assertEquals($expected, $result);
Expand Down
2 changes: 1 addition & 1 deletion tests/comparisons/Model/testBakeTableRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function initialize(array $config): void
public function buildRules(RulesChecker $rules): RulesChecker
{
$rules->add($rules->isUnique(['username']), ['errorField' => 'username']);
$rules->add($rules->isUnique(['field_1', 'field_2'], ['allowMultipleNulls' => true]), ['errorField' => 'field_1']);
$rules->add($rules->isUnique(['field_1', 'field_2'], ['allowMultipleNulls' => true]), ['errorField' => 'field_1', 'message' => __('This combination of field_1 and field_2 already exists')]);

return $rules;
}
Expand Down
4 changes: 2 additions & 2 deletions tests/schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,8 @@
'table' => 'datatypes',
'columns' => [
'id' => ['type' => 'integer', 'null' => false],
'decimal_field' => ['type' => 'decimal', 'length' => '6', 'precision' => 3, 'default' => '0.000'],
'float_field' => ['type' => 'float', 'length' => '5,2', 'null' => false, 'default' => null],
'decimal_field' => ['type' => 'decimal', 'length' => 6, 'precision' => 3, 'default' => '0.000'],
'float_field' => ['type' => 'float', 'length' => 5, 'precision' => 2, 'null' => false, 'default' => null],
'huge_int' => ['type' => 'biginteger'],
'small_int' => ['type' => 'smallinteger'],
'tiny_int' => ['type' => 'tinyinteger'],
Expand Down
10 changes: 10 additions & 0 deletions tests/test_app/App/Plugin/FixtureTest/src/FixtureTestPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace FixtureTest;

use Cake\Core\BasePlugin;

class FixtureTestPlugin extends BasePlugin
{
}
10 changes: 10 additions & 0 deletions tests/test_app/App/Plugin/TestTemplate/src/TestTemplatePlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace TestTemplate;

use Cake\Core\BasePlugin;

class TestTemplatePlugin extends BasePlugin
{
}
10 changes: 10 additions & 0 deletions tests/test_app/App/Plugin/TestTest/src/TestTestPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace TestTest;

use Cake\Core\BasePlugin;

class TestTestPlugin extends BasePlugin
{
}
10 changes: 10 additions & 0 deletions tests/test_app/Plugin/Authentication/src/AuthenticationPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace Authentication;

use Cake\Core\BasePlugin;

class AuthenticationPlugin extends BasePlugin
{
}
10 changes: 10 additions & 0 deletions tests/test_app/Plugin/BakeTest/src/BakeTestPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace BakeTest;

use Cake\Core\BasePlugin;

class BakeTestPlugin extends BasePlugin
{
}
10 changes: 10 additions & 0 deletions tests/test_app/Plugin/Company/Pastry/src/PastryPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace Company\Pastry;

use Cake\Core\BasePlugin;

class PastryPlugin extends BasePlugin
{
}
10 changes: 10 additions & 0 deletions tests/test_app/Plugin/TestBake/src/TestBakePlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace TestBake;

use Cake\Core\BasePlugin;

class TestBakePlugin extends BasePlugin
{
}
10 changes: 10 additions & 0 deletions tests/test_app/Plugin/TestBakeTheme/src/TestBakeThemePlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace TestBakeTheme;

use Cake\Core\BasePlugin;

class TestBakeThemePlugin extends BasePlugin
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace WithBakeSubFolder;

use Cake\Core\BasePlugin;

class WithBakeSubFolderPlugin extends BasePlugin
{
}