diff --git a/Cake/ORM/Table.php b/Cake/ORM/Table.php index d859f668c3f..ecde889f6c6 100644 --- a/Cake/ORM/Table.php +++ b/Cake/ORM/Table.php @@ -1057,11 +1057,28 @@ protected function _processValidation($entity, $options) { $type = is_string($options['validate']) ? $options['validate'] : 'default'; $validator = $this->validator($type); + $pass = compact('entity', 'options', 'validator'); + $event = new Event('Model.beforeValidate', $this, $pass); + $this->getEventManager()->dispatch($event); + + if ($event->isStopped()) { + return (bool)$event->result; + } + if (!count($validator)) { return true; } - return $entity->validate($validator, $options['fieldList']); + $success = $entity->validate($validator, $options['fieldList']); + + $event = new Event('Model.afterValidate', $this, $pass); + $this->getEventManager()->dispatch($event); + + if ($event->isStopped()) { + $success = (bool)$event->result; + } + + return $success; } /** diff --git a/Cake/Test/TestCase/ORM/TableTest.php b/Cake/Test/TestCase/ORM/TableTest.php index 0a3707f1aa4..6ba0ad9024d 100644 --- a/Cake/Test/TestCase/ORM/TableTest.php +++ b/Cake/Test/TestCase/ORM/TableTest.php @@ -1903,4 +1903,68 @@ public function testSaveWithValidationSuccess() { $this->assertEmpty($entity->errors('password')); } +/** + * Tests beforeValidate event is triggered + * + * @return void + */ + public function testBeforeValidate() { + $entity = new \Cake\ORM\Entity([ + 'username' => 'superuser' + ]); + $table = TableRegistry::get('users'); + $table->getEventManager()->attach(function($ev, $en, $opt, $val) use ($entity) { + $this->assertSame($entity, $en); + $this->assertTrue($opt['crazy']); + $this->assertSame($ev->subject()->validator('default'), $val); + $val->validatePresence('password'); + }, 'Model.beforeValidate'); + $this->assertFalse($table->save($entity, ['crazy' => true])); + $this->assertNotEmpty($entity->errors('password')); + } + +/** + * Tests that beforeValidate can set the validation result + * + * @return void + */ + public function testBeforeValidateSetResult() { + $entity = new \Cake\ORM\Entity([ + 'username' => 'superuser' + ]); + $table = TableRegistry::get('users'); + $table->getEventManager()->attach(function($ev, $en) { + $en->errors('username', 'Not good'); + return false; + }, 'Model.beforeValidate'); + $this->assertFalse($table->save($entity)); + $this->assertEquals(['Not good'], $entity->errors('username')); + } + +/** + * Tests that afterValidate is triggered and can set a result + * + * @return void + */ + public function testAfterValidate() { + $entity = new \Cake\ORM\Entity([ + 'username' => 'superuser', + 'password' => 'hey' + ]); + $table = TableRegistry::get('users'); + $table->validator()->validatePresence('password'); + $table->getEventManager()->attach(function($ev, $en, $opt, $val) use ($entity) { + $this->assertSame($entity, $en); + $this->assertTrue($opt['crazy']); + $this->assertSame($ev->subject()->validator('default'), $val); + + $en->errors('username', 'Not good'); + return false; + }, 'Model.afterValidate'); + + $this->assertFalse($table->save($entity, ['crazy' => true])); + $this->assertEmpty($entity->errors('password')); + $this->assertEquals(['Not good'], $entity->errors('username')); + } + }