ソースを参照

3rd allowPartialNulls implementation

Jonas 9 年 前
コミット
230e06fca7
2 ファイル変更88 行追加30 行削除
  1. 11 27
      src/ORM/Rule/ExistsIn.php
  2. 77 3
      tests/TestCase/ORM/RulesCheckerIntegrationTest.php

+ 11 - 27
src/ORM/Rule/ExistsIn.php

@@ -110,13 +110,20 @@ class ExistsIn
             return true;
         }
 
-        if ($this->_options['allowPartialNulls'] && $this->_checkPartialSchemaNulls($entity, $source)) {
-            return true;
-        }
         if ($this->_fieldsAreNull($entity, $source)) {
             return true;
         }
 
+        if ($this->_options['allowPartialNulls']) {
+            $schema = $source->schema();
+            foreach ($this->_fields as $i => $field) {
+                if ($schema->column($field) && $schema->isNullable($field) && $entity->get($field) === null) {
+                    unset($bindingKey[$i]);
+                    unset($this->_fields[$i]);
+                }
+            }
+        }
+
         $primary = array_map(
             [$target, 'aliasField'],
             $bindingKey
@@ -125,6 +132,7 @@ class ExistsIn
             $primary,
             $entity->extract($this->_fields)
         );
+
         return $target->exists($conditions);
     }
 
@@ -146,28 +154,4 @@ class ExistsIn
         }
         return $nulls === count($this->_fields);
     }
-
-    /**
-     * Checks whether or not the give entity fields are null and map to schema NULL
-     * or are not null and map to schema NOT NULL.
-     *
-     * @param \Cake\Datasource\EntityInterface $entity The entity to check.
-     * @param \Cake\ORM\Table $source The table to use schema from.
-     * @return bool
-     */
-    protected function _checkPartialSchemaNulls($entity, $source)
-    {
-        $schema = $source->schema();
-        foreach ($this->_fields as $field) {
-            $isNullable = $schema->isNullable($field);
-            $value = $entity->get($field);
-            if (!$isNullable && $value === null) {
-                return false;
-            }
-            if ($isNullable && $value !== null) {
-                return false;
-            }
-        }
-        return true;
-    }
 }

+ 77 - 3
tests/TestCase/ORM/RulesCheckerIntegrationTest.php

@@ -1025,7 +1025,7 @@ class RulesCheckerIntegrationTest extends TestCase
 
         $rules->add($rules->existsIn(['author_id', 'site_id'], 'SiteAuthors', [
             'allowPartialNulls' => true,
-            'message' => 'will not occur']));
+            'message' => 'will not error']));
         $this->assertInstanceOf('Cake\ORM\Entity', $table->save($entity));
     }
 
@@ -1034,7 +1034,7 @@ class RulesCheckerIntegrationTest extends TestCase
      *
      * @return
      */
-    public function testExistsInAllowPartialNullsWithAuthorId1G()
+    public function testExistsInAllowPartialNullsWithAuthorId1F()
     {
         $entity = new Entity([
             'id' => 10,
@@ -1048,11 +1048,85 @@ class RulesCheckerIntegrationTest extends TestCase
 
         $rules->add($rules->existsIn(['author_id', 'site_id'], 'SiteAuthors', [
             'allowPartialNulls' => false,
-            'message' => 'will not occur']));
+            'message' => 'will not error']));
         $this->assertInstanceOf('Cake\ORM\Entity', $table->save($entity));
     }
 
     /**
+     * Tests new allowPartialNulls flag with author id set to 99999999 (does not exist)
+     *
+     * @return
+     */
+    public function testExistsInAllowPartialNullsWithAuthorId1G()
+    {
+        $entity = new Entity([
+            'id' => 10,
+            'author_id' => 99999999,
+            'site_id' => 1,
+            'name' => 'New Site Article with Author',
+        ]);
+        $table = TableRegistry::get('SiteArticles');
+        $table->belongsTo('SiteAuthors');
+        $rules = $table->rulesChecker();
+
+        $rules->add($rules->existsIn(['author_id', 'site_id'], 'SiteAuthors', [
+            'allowPartialNulls' => true,
+            'message' => 'will error']));
+        $this->assertFalse($table->save($entity));
+        $this->assertEquals(['author_id' => ['_existsIn' => 'will error']], $entity->errors());
+    }
+
+    /**
+     * Tests new allowPartialNulls flag with author id set to 99999999 (does not exist)
+     * and site_id set to 99999999 (does not exist)
+     *
+     * @return
+     */
+    public function testExistsInAllowPartialNullsWithAuthorId1H()
+    {
+        $entity = new Entity([
+            'id' => 10,
+            'author_id' => 99999999,
+            'site_id' => 99999999,
+            'name' => 'New Site Article with Author',
+        ]);
+        $table = TableRegistry::get('SiteArticles');
+        $table->belongsTo('SiteAuthors');
+        $rules = $table->rulesChecker();
+
+        $rules->add($rules->existsIn(['author_id', 'site_id'], 'SiteAuthors', [
+            'allowPartialNulls' => true,
+            'message' => 'will error']));
+        $this->assertFalse($table->save($entity));
+        $this->assertEquals(['author_id' => ['_existsIn' => 'will error']], $entity->errors());
+    }
+
+    /**
+     * Tests new allowPartialNulls flag with author id set to 1 (does exist)
+     * and site_id set to 99999999 (does not exist)
+     *
+     * @return
+     */
+    public function testExistsInAllowPartialNullsWithAuthorId1I()
+    {
+        $entity = new Entity([
+            'id' => 10,
+            'author_id' => 1,
+            'site_id' => 99999999,
+            'name' => 'New Site Article with Author',
+        ]);
+        $table = TableRegistry::get('SiteArticles');
+        $table->belongsTo('SiteAuthors');
+        $rules = $table->rulesChecker();
+
+        $rules->add($rules->existsIn(['author_id', 'site_id'], 'SiteAuthors', [
+            'allowPartialNulls' => true,
+            'message' => 'will error']));
+        $this->assertFalse($table->save($entity));
+        $this->assertEquals(['author_id' => ['_existsIn' => 'will error']], $entity->errors());
+    }
+
+    /**
      * Tests using rules to prevent delete operations
      *
      * @group delete