Skip to content

Commit

Permalink
Added checks to prevent adding rules with the same name (cakephp#17859)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicosp authored Aug 29, 2024
1 parent e13084a commit 58c94f9
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/Datasource/RulesChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
namespace Cake\Datasource;

use Cake\Core\Exception\CakeException;
use InvalidArgumentException;

/**
Expand Down Expand Up @@ -133,10 +134,12 @@ public function __construct(array $options = [])
* @param array<string, mixed> $options List of extra options to pass to the rule callable as
* second argument.
* @return $this
* @throws \Cake\Core\Exception\CakeException If a rule with the same name already exists
*/
public function add(callable $rule, array|string|null $name = null, array $options = [])
{
if (is_string($name)) {
$this->checkName($name, $this->_rules);
$this->_rules[$name] = $this->_addError($rule, $name, $options);
} else {
$this->_rules[] = $this->_addError($rule, $name, $options);
Expand Down Expand Up @@ -176,10 +179,12 @@ public function remove(string $name)
* @param array<string, mixed> $options List of extra options to pass to the rule callable as
* second argument.
* @return $this
* @throws \Cake\Core\Exception\CakeException If a rule with the same name already exists
*/
public function addCreate(callable $rule, array|string|null $name = null, array $options = [])
{
if (is_string($name)) {
$this->checkName($name, $this->_createRules);
$this->_createRules[$name] = $this->_addError($rule, $name, $options);
} else {
$this->_createRules[] = $this->_addError($rule, $name, $options);
Expand Down Expand Up @@ -219,10 +224,12 @@ public function removeCreate(string $name)
* @param array<string, mixed> $options List of extra options to pass to the rule callable as
* second argument.
* @return $this
* @throws \Cake\Core\Exception\CakeException If a rule with the same name already exists
*/
public function addUpdate(callable $rule, array|string|null $name = null, array $options = [])
{
if (is_string($name)) {
$this->checkName($name, $this->_updateRules);
$this->_updateRules[$name] = $this->_addError($rule, $name, $options);
} else {
$this->_updateRules[] = $this->_addError($rule, $name, $options);
Expand Down Expand Up @@ -262,10 +269,12 @@ public function removeUpdate(string $name)
* @param array<string, mixed> $options List of extra options to pass to the rule callable as
* second argument.
* @return $this
* @throws \Cake\Core\Exception\CakeException If a rule with the same name already exists
*/
public function addDelete(callable $rule, array|string|null $name = null, array $options = [])
{
if (is_string($name)) {
$this->checkName($name, $this->_deleteRules);
$this->_deleteRules[$name] = $this->_addError($rule, $name, $options);
} else {
$this->_deleteRules[] = $this->_addError($rule, $name, $options);
Expand Down Expand Up @@ -404,4 +413,19 @@ protected function _addError(callable $rule, array|string|null $name = null, arr

return $rule;
}

/**
* Checks that a rule with the same name doesn't already exist
*
* @param string $name The name to check
* @param array<\Cake\Datasource\RuleInvoker> $rules The rules array to check
* @return void
* @throws \Cake\Core\Exception\CakeException
*/
protected function checkName(string $name, array $rules): void
{
if (array_key_exists($name, $rules)) {
throw new CakeException('A rule with the same name already exists');
}
}
}
41 changes: 41 additions & 0 deletions tests/TestCase/Datasource/RulesCheckerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
namespace Cake\Test\TestCase\Datasource;

use Cake\Core\Exception\CakeException;
use Cake\Datasource\RulesChecker;
use Cake\ORM\Entity;
use Cake\TestSuite\TestCase;
Expand Down Expand Up @@ -258,4 +259,44 @@ function () {
$rules->removeDelete('ruleName');
$this->assertTrue($rules->check($entity, RulesChecker::DELETE));
}

public function testAddDuplicateName(): void
{
$rules = new RulesChecker();
$rules->add(fn () => false, 'myUniqueName');

$this->expectException(CakeException::class);
$rules->add(fn () => true, 'myUniqueName');
$this->fail('Exception not thrown');
}

public function testAddCreateDuplicateName(): void
{
$rules = new RulesChecker();
$rules->addCreate(fn () => false, 'myUniqueName');

$this->expectException(CakeException::class);
$rules->addCreate(fn () => true, 'myUniqueName');
$this->fail('Exception not thrown');
}

public function testAddUpdateDuplicateName(): void
{
$rules = new RulesChecker();
$rules->addUpdate(fn () => false, 'myUniqueName');

$this->expectException(CakeException::class);
$rules->addUpdate(fn () => true, 'myUniqueName');
$this->fail('Exception not thrown');
}

public function testAddDeleteDuplicateName(): void
{
$rules = new RulesChecker();
$rules->addDelete(fn () => false, 'myUniqueName');

$this->expectException(CakeException::class);
$rules->addDelete(fn () => true, 'myUniqueName');
$this->fail('Exception not thrown');
}
}

0 comments on commit 58c94f9

Please sign in to comment.