Browse Source

String return values from rules should trigger errors.

This makes rules and validation more consistent. Returning a string from
a rule always triggers a validation failure, but only when the
errorField is defined does an error message get populated.

Refs #6181
Mark Story 11 years ago
parent
commit
cb308f0c5e
2 changed files with 55 additions and 6 deletions
  1. 11 6
      src/ORM/RulesChecker.php
  2. 44 0
      tests/TestCase/ORM/RulesCheckerIntegrationTest.php

+ 11 - 6
src/ORM/RulesChecker.php

@@ -376,19 +376,24 @@ class RulesChecker
 
         return function ($entity, $scope) use ($rule, $name, $options) {
             $pass = $rule($entity, $options + $scope);
-
-            if ($pass || empty($options['errorField'])) {
-                return $pass;
+            if ($pass === true || empty($options['errorField'])) {
+                return $pass === true;
             }
 
-            $message = isset($options['message']) ? $options['message'] : 'invalid';
+            $message = 'invalid';
+            if (isset($options['message'])) {
+                $message = $options['message'];
+            }
+            if (is_string($pass)) {
+                $message = $pass;
+            }
             if ($name) {
                 $message = [$name => $message];
             } else {
-                $message = (array)$message;
+                $message = [$message];
             }
             $entity->errors($options['errorField'], $message);
-            return $pass;
+            return $pass === true;
         };
     }
 }

+ 44 - 0
tests/TestCase/ORM/RulesCheckerIntegrationTest.php

@@ -716,6 +716,50 @@ class RulesCheckerIntegrationTest extends TestCase
     }
 
     /**
+     * Test adding rules that return error string
+     *
+     * @group save
+     * @return void
+     */
+    public function testCustomErrorMessageFromRule()
+    {
+        $entity = new Entity([
+            'name' => 'larry'
+        ]);
+
+        $table = TableRegistry::get('Authors');
+        $rules = $table->rulesChecker();
+        $rules->add(function () {
+            return 'So much nope';
+        }, ['errorField' => 'name']);
+
+        $this->assertFalse($table->save($entity));
+        $this->assertEquals(['So much nope'], $entity->errors('name'));
+    }
+
+    /**
+     * Test adding rules with no errorField do not accept strings
+     *
+     * @group save
+     * @return void
+     */
+    public function testCustomErrorMessageFromRuleNoErrorField()
+    {
+        $entity = new Entity([
+            'name' => 'larry'
+        ]);
+
+        $table = TableRegistry::get('Authors');
+        $rules = $table->rulesChecker();
+        $rules->add(function () {
+            return 'So much nope';
+        });
+
+        $this->assertFalse($table->save($entity));
+        $this->assertEmpty($entity->errors());
+    }
+
+    /**
      * Tests that using existsIn for a hasMany association will not be called
      * as the foreign key for the association was automatically validated already.
      *