Skip to content

Commit

Permalink
Prevented unneeded existsIn check for automatically saved hasMany
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Dec 26, 2014
1 parent 1ff7c4a commit 6b9bf35
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/ORM/Association/HasMany.php
Expand Up @@ -90,6 +90,7 @@ public function saveAssociated(EntityInterface $entity, array $options = []) {
);
$target = $this->target();
$original = $targetEntities;
$options['_sourceTable'] = $this->source();

foreach ($targetEntities as $k => $targetEntity) {
if (!($targetEntity instanceof EntityInterface)) {
Expand Down
10 changes: 10 additions & 0 deletions src/ORM/Rule/ExistsIn.php
Expand Up @@ -15,6 +15,7 @@
namespace Cake\ORM\Rule;

use Cake\Datasource\EntityInterface;
use Cake\ORM\Association;

/**
* Checks that the value provided in a field exists as the primary key of another
Expand Down Expand Up @@ -61,6 +62,15 @@ public function __invoke(EntityInterface $entity, array $options) {
$this->_repository = $options['repository']->association($this->_repository);
}

if (!empty($options['_sourceTable'])) {
$source = $this->_repository instanceof Association ?
$this->_repository->target() :
$this->_repository;
if ($source === $options['_sourceTable']) {
return true;
}
}

if (!$entity->extract($this->_fields, true)) {
return true;
}
Expand Down
43 changes: 42 additions & 1 deletion tests/TestCase/ORM/RulesCheckerIntegrationTest.php
Expand Up @@ -135,7 +135,8 @@ public function testSaveHasManyWithErrorsAtomic() {
$table->association('articles')
->target()
->rulesChecker()
->add(function (Entity $entity) {
->add(function (Entity $entity, $options) use ($table) {
$this->assertSame($table, $options['_sourceTable']);
return $entity->title === '1';
}, ['errorField' => 'title', 'message' => 'This is an error']);

Expand Down Expand Up @@ -562,4 +563,44 @@ public function testCustomOptionsPassingDelete() {
$entity = $table->get(1);
$this->assertFalse($table->delete($entity, ['foo' => 'bar']));
}

/**
* Tests that using existsIn for a hasMany association will not be called
* as the foreign key for the association was automatically validated already.
*
* @group save
* @return void
*/
public function testAvoidExistsInOnAutomaticSaving() {
$entity = new \Cake\ORM\Entity([
'name' => 'Jose'
]);
$entity->articles = [
new \Cake\ORM\Entity([
'title' => '1',
'body' => 'A body'
]),
new \Cake\ORM\Entity([
'title' => 'Another Title',
'body' => 'Another body'
])
];

$table = TableRegistry::get('authors');
$table->hasMany('articles');
$table->association('articles')->belongsTo('authors');
$checker = $table->association('articles')->target()->rulesChecker();
$checker->add(function ($entity, $options) use ($checker) {
$rule = $checker->existsIn('author_id', 'authors');
$id = $entity->author_id;
$entity->author_id = 5000;
$result = $rule($entity, $options);
$this->assertTrue($result);
$entity->author_id = $id;
return true;
});

$this->assertSame($entity, $table->save($entity));
}

}

0 comments on commit 6b9bf35

Please sign in to comment.