Browse Source

Prevented unneeded existsIn check for automatically saved hasMany

Jose Lorenzo Rodriguez 11 years ago
parent
commit
6b9bf35143

+ 1 - 0
src/ORM/Association/HasMany.php

@@ -90,6 +90,7 @@ class HasMany extends Association {
 		);
 		$target = $this->target();
 		$original = $targetEntities;
+		$options['_sourceTable'] = $this->source();
 
 		foreach ($targetEntities as $k => $targetEntity) {
 			if (!($targetEntity instanceof EntityInterface)) {

+ 10 - 0
src/ORM/Rule/ExistsIn.php

@@ -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
@@ -61,6 +62,15 @@ class ExistsIn {
 			$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;
 		}

+ 42 - 1
tests/TestCase/ORM/RulesCheckerIntegrationTest.php

@@ -135,7 +135,8 @@ class RulesCheckerIntegrationTest extends TestCase {
 		$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']);
 
@@ -562,4 +563,44 @@ class RulesCheckerIntegrationTest extends TestCase {
 		$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));
+	}
+
 }