Added unit tests to cover all eventlistener events, fixed fatal transaction bug
This commit is contained in:
parent
0a8123cf7a
commit
96177e3e22
@ -45,7 +45,7 @@ abstract class Doctrine_Configurable {
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
final public function setAttribute($attribute,$value) {
|
||||
public function setAttribute($attribute,$value) {
|
||||
switch($attribute):
|
||||
case Doctrine::ATTR_BATCH_SIZE:
|
||||
if($value < 0)
|
||||
@ -126,13 +126,51 @@ abstract class Doctrine_Configurable {
|
||||
* @param Doctrine_EventListener $listener
|
||||
* @return void
|
||||
*/
|
||||
final public function setEventListener($listener) {
|
||||
$i = Doctrine::ATTR_LISTENER;
|
||||
if( ! ($listener instanceof Doctrine_EventListener) &&
|
||||
! ($listener instanceof Doctrine_EventListener_Chain))
|
||||
throw new Doctrine_Exception("EventListener must extend Doctrine_EventListener or Doctrine_EventListener_Chain");
|
||||
public function setEventListener($listener) {
|
||||
return $this->setListener($listener);
|
||||
}
|
||||
/**
|
||||
* addListener
|
||||
*
|
||||
* @param Doctrine_DB_EventListener_Interface|Doctrine_Overloadable $listener
|
||||
* @return Doctrine_DB
|
||||
*/
|
||||
public function addListener($listener, $name = null) {
|
||||
if( ! ($this->attributes[Doctrine::ATTR_LISTENER] instanceof Doctrine_EventListener_Chain))
|
||||
$this->attributes[Doctrine::ATTR_LISTENER] = new Doctrine_EventListener_Chain();
|
||||
|
||||
$this->attributes[$i] = $listener;
|
||||
$this->attributes[Doctrine::ATTR_LISTENER]->add($listener, $name);
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* getListener
|
||||
*
|
||||
* @return Doctrine_DB_EventListener_Interface|Doctrine_Overloadable
|
||||
*/
|
||||
public function getListener() {
|
||||
if( ! isset($this->attributes[Doctrine::ATTR_LISTENER])) {
|
||||
if(isset($this->parent))
|
||||
return $this->parent->getListener();
|
||||
|
||||
return null;
|
||||
}
|
||||
return $this->attributes[Doctrine::ATTR_LISTENER];
|
||||
}
|
||||
/**
|
||||
* setListener
|
||||
*
|
||||
* @param Doctrine_DB_EventListener_Interface|Doctrine_Overloadable $listener
|
||||
* @return Doctrine_DB
|
||||
*/
|
||||
public function setListener($listener) {
|
||||
if( ! ($listener instanceof Doctrine_EventListener_Interface) &&
|
||||
! ($listener instanceof Doctrine_Overloadable))
|
||||
throw new Doctrine_DB_Exception("Couldn't set eventlistener. EventListeners should implement either Doctrine_EventListener_Interface or Doctrine_Overloadable");
|
||||
|
||||
$this->attributes[Doctrine::ATTR_LISTENER] = $listener;
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* returns the value of an attribute
|
||||
@ -140,7 +178,7 @@ abstract class Doctrine_Configurable {
|
||||
* @param integer $attribute
|
||||
* @return mixed
|
||||
*/
|
||||
final public function getAttribute($attribute) {
|
||||
public function getAttribute($attribute) {
|
||||
$attribute = (int) $attribute;
|
||||
|
||||
if($attribute < 1 || $attribute > 17)
|
||||
@ -160,7 +198,7 @@ abstract class Doctrine_Configurable {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
final public function getAttributes() {
|
||||
public function getAttributes() {
|
||||
return $this->attributes;
|
||||
}
|
||||
/**
|
||||
@ -170,7 +208,7 @@ abstract class Doctrine_Configurable {
|
||||
* @param Doctrine_Configurable $component
|
||||
* @return void
|
||||
*/
|
||||
final public function setParent(Doctrine_Configurable $component) {
|
||||
public function setParent(Doctrine_Configurable $component) {
|
||||
$this->parent = $component;
|
||||
}
|
||||
/**
|
||||
@ -179,7 +217,7 @@ abstract class Doctrine_Configurable {
|
||||
*
|
||||
* @return Doctrine_Configurable
|
||||
*/
|
||||
final public function getParent() {
|
||||
public function getParent() {
|
||||
return $this->parent;
|
||||
}
|
||||
}
|
||||
|
@ -150,34 +150,31 @@ class Doctrine_Connection_Transaction implements Countable, IteratorAggregate {
|
||||
$this->validator = new Doctrine_Validator();
|
||||
|
||||
try {
|
||||
|
||||
|
||||
$this->bulkInsert();
|
||||
$this->bulkUpdate();
|
||||
$this->bulkDelete();
|
||||
|
||||
if($this->conn->getAttribute(Doctrine::ATTR_VLD)) {
|
||||
|
||||
if($this->validator->hasErrors()) {
|
||||
$this->rollback();
|
||||
throw new Doctrine_Validator_Exception($this->validator);
|
||||
}
|
||||
}
|
||||
|
||||
$this->conn->getDBH()->commit();
|
||||
|
||||
} catch(PDOException $e) {
|
||||
} catch(Exception $e) {
|
||||
$this->rollback();
|
||||
|
||||
throw new Doctrine_Exception($e->__toString());
|
||||
}
|
||||
|
||||
|
||||
if($this->conn->getAttribute(Doctrine::ATTR_VLD)) {
|
||||
if($this->validator->hasErrors()) {
|
||||
$this->rollback();
|
||||
throw new Doctrine_Validator_Exception($this->validator);
|
||||
}
|
||||
}
|
||||
|
||||
$this->conn->getDBH()->commit();
|
||||
|
||||
$this->conn->getAttribute(Doctrine::ATTR_LISTENER)->onTransactionCommit($this->conn);
|
||||
|
||||
$this->delete = array();
|
||||
$this->state = Doctrine_Connection_Transaction::STATE_OPEN;
|
||||
|
||||
$this->state = Doctrine_Connection_Transaction::STATE_OPEN;
|
||||
$this->validator = null;
|
||||
|
||||
|
||||
} elseif($this->transaction_level == 1)
|
||||
$this->state = Doctrine_Connection_Transaction::STATE_ACTIVE;
|
||||
}
|
||||
@ -192,6 +189,10 @@ class Doctrine_Connection_Transaction implements Countable, IteratorAggregate {
|
||||
*/
|
||||
public function rollback() {
|
||||
$this->conn->getAttribute(Doctrine::ATTR_LISTENER)->onPreTransactionRollback($this->conn);
|
||||
|
||||
$this->delete = array();
|
||||
$this->insert = array();
|
||||
$this->update = array();
|
||||
|
||||
$this->transaction_level = 0;
|
||||
$this->conn->getDBH()->rollback();
|
||||
@ -295,12 +296,18 @@ class Doctrine_Connection_Transaction implements Countable, IteratorAggregate {
|
||||
$record->assignIdentifier(false);
|
||||
}
|
||||
if($record instanceof Doctrine_Record) {
|
||||
|
||||
$table = $record->getTable();
|
||||
|
||||
$table->getListener()->onPreDelete($record);
|
||||
|
||||
$params = substr(str_repeat("?, ",count($ids)),0,-2);
|
||||
$query = "DELETE FROM ".$record->getTable()->getTableName()." WHERE ".$table->getIdentifier()." IN(".$params.")";
|
||||
$this->conn->execute($query,$ids);
|
||||
|
||||
$table->getListener()->onDelete($record);
|
||||
}
|
||||
|
||||
}
|
||||
$this->delete = array();
|
||||
}
|
||||
|
@ -79,7 +79,4 @@ abstract class Doctrine_EventListener implements Doctrine_EventListener_Interfac
|
||||
|
||||
public function onCollectionDelete(Doctrine_Collection $collection) { }
|
||||
public function onPreCollectionDelete(Doctrine_Collection $collection) { }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -167,12 +167,14 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
// listen the onPreCreate event
|
||||
$this->table->getAttribute(Doctrine::ATTR_LISTENER)->onPreCreate($this);
|
||||
} else {
|
||||
|
||||
// listen the onPreLoad event
|
||||
$this->table->getAttribute(Doctrine::ATTR_LISTENER)->onPreLoad($this);
|
||||
}
|
||||
// get the data array
|
||||
$this->data = $this->table->getData();
|
||||
|
||||
|
||||
// get the column count
|
||||
$count = count($this->data);
|
||||
|
||||
|
@ -831,7 +831,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable {
|
||||
|
||||
if(isset($this->identityMap[$id]))
|
||||
$record = $this->identityMap[$id];
|
||||
else {
|
||||
else {
|
||||
$record = new $this->name($this);
|
||||
$this->identityMap[$id] = $record;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.php");
|
||||
class EventListenerClainTest extends Doctrine_Record {
|
||||
class EventListenerChainTest extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("name", "string", 100);
|
||||
}
|
||||
@ -23,7 +23,7 @@ class Doctrine_EventListener_TestB extends Doctrine_EventListener {
|
||||
}
|
||||
}
|
||||
|
||||
class Doctrine_EventListenerChainTestCase extends Doctrine_UnitTestCase {
|
||||
class Doctrine_EventListener_Chain_TestCase extends Doctrine_UnitTestCase {
|
||||
public function testEvents() {
|
||||
$connection = $this->manager->openConnection(Doctrine_DB::getConn("sqlite::memory:"));
|
||||
$debug = $this->listener->getMessages();
|
@ -15,15 +15,30 @@ class EventListenerTest extends Doctrine_Record {
|
||||
return md5($password);
|
||||
}
|
||||
}
|
||||
class Doctrine_EventListener_TestLogger implements Doctrine_Overloadable, Countable {
|
||||
private $messages = array();
|
||||
|
||||
public function __call($m, $a) {
|
||||
|
||||
$this->messages[] = $m;
|
||||
}
|
||||
public function pop() {
|
||||
return array_pop($this->messages);
|
||||
}
|
||||
public function clear() {
|
||||
$this->messages = array();
|
||||
}
|
||||
public function getAll() {
|
||||
return $this->messages;
|
||||
}
|
||||
public function count() {
|
||||
return count($this->messages);
|
||||
}
|
||||
}
|
||||
|
||||
class Doctrine_EventListenerTestCase extends Doctrine_UnitTestCase {
|
||||
public function testEvents() {
|
||||
$connection = $this->manager->openConnection(Doctrine_DB::getConn("sqlite::memory:"));
|
||||
$debug = $this->listener->getMessages();
|
||||
$last = end($debug);
|
||||
$this->assertTrue($last->getObject() instanceof Doctrine_Connection);
|
||||
$this->assertTrue($last->getCode() == Doctrine_EventListener_Debugger::EVENT_OPEN);
|
||||
}
|
||||
private $logger;
|
||||
|
||||
public function testAccessorInvoker() {
|
||||
$e = new EventListenerTest;
|
||||
$e->name = "something";
|
||||
@ -61,7 +76,127 @@ class Doctrine_EventListenerTestCase extends Doctrine_UnitTestCase {
|
||||
$this->assertEqual($e->name, 'SOMETHING');
|
||||
$this->assertEqual($e->rawGet('name'), 'something');
|
||||
$this->assertEqual($e->password, '202cb962ac59075b964b07152d234b70');
|
||||
|
||||
}
|
||||
public function testSetListener() {
|
||||
$this->logger = new Doctrine_EventListener_TestLogger();
|
||||
|
||||
$e = new EventListenerTest;
|
||||
|
||||
$e->getTable()->setListener($this->logger);
|
||||
|
||||
$this->assertEqual($e->getTable()->getListener(), $this->logger);
|
||||
}
|
||||
public function testOnLoad() {
|
||||
$this->logger->clear();
|
||||
$this->assertEqual($this->connection->getTable('EventListenerTest')->getListener(), $this->logger);
|
||||
$this->connection->clear();
|
||||
|
||||
$e = $this->connection->getTable('EventListenerTest')->find(1);
|
||||
|
||||
$this->assertEqual($e->getTable()->getListener(), $this->logger);
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onLoad');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreLoad');
|
||||
}
|
||||
|
||||
public function testOnCreate() {
|
||||
$e = new EventListenerTest;
|
||||
|
||||
|
||||
$e->setListener($this->logger);
|
||||
$this->logger->clear();
|
||||
$e = new EventListenerTest;
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onCreate');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreCreate');
|
||||
$this->assertEqual($this->logger->count(), 0);
|
||||
}
|
||||
public function testOnSleepAndOnWakeUp() {
|
||||
$e = new EventListenerTest;
|
||||
|
||||
$this->logger->clear();
|
||||
|
||||
$s = serialize($e);
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onSleep');
|
||||
$this->assertEqual($this->logger->count(), 0);
|
||||
|
||||
$e = unserialize($s);
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onWakeUp');
|
||||
$this->assertEqual($this->logger->count(), 0);
|
||||
}
|
||||
public function testTransaction() {
|
||||
$e = new EventListenerTest();
|
||||
$e->name = "test 1";
|
||||
|
||||
$this->logger->clear();
|
||||
|
||||
$e->save();
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onSave');
|
||||
$this->assertEqual($this->logger->pop(), 'onInsert');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreInsert');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreSave');
|
||||
|
||||
$e->name = "test 2";
|
||||
|
||||
$e->save();
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onSave');
|
||||
$this->assertEqual($this->logger->pop(), 'onUpdate');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreUpdate');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreSave');
|
||||
|
||||
$this->logger->clear();
|
||||
|
||||
$e->delete();
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onDelete');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreDelete');
|
||||
}
|
||||
public function testTransactionWithConnectionListener() {
|
||||
$e = new EventListenerTest();
|
||||
$e->getTable()->getConnection()->setListener($this->logger);
|
||||
|
||||
$e->name = "test 2";
|
||||
|
||||
$this->logger->clear();
|
||||
|
||||
$e->save();
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onTransactionCommit');
|
||||
$this->assertEqual($this->logger->pop(), 'onSave');
|
||||
$this->assertEqual($this->logger->pop(), 'onInsert');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreInsert');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreSave');
|
||||
$this->assertEqual($this->logger->pop(), 'onTransactionBegin');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreTransactionBegin');
|
||||
|
||||
$e->name = "test 1";
|
||||
|
||||
$e->save();
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onTransactionCommit');
|
||||
$this->assertEqual($this->logger->pop(), 'onSave');
|
||||
$this->assertEqual($this->logger->pop(), 'onUpdate');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreUpdate');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreSave');
|
||||
$this->assertEqual($this->logger->pop(), 'onTransactionBegin');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreTransactionBegin');
|
||||
|
||||
$this->logger->clear();
|
||||
|
||||
$e->delete();
|
||||
|
||||
$this->assertEqual($this->logger->pop(), 'onTransactionCommit');
|
||||
$this->assertEqual($this->logger->pop(), 'onDelete');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreDelete');
|
||||
$this->assertEqual($this->logger->pop(), 'onTransactionBegin');
|
||||
$this->assertEqual($this->logger->pop(), 'onPreTransactionBegin');
|
||||
}
|
||||
|
||||
public function prepareData() { }
|
||||
public function prepareTables() {
|
||||
$this->tables = array('EventListenerTest');
|
||||
|
@ -9,6 +9,20 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase {
|
||||
$this->tables[] = "GzipTest";
|
||||
parent::prepareTables();
|
||||
}
|
||||
public function testNotNullConstraint() {
|
||||
$null = new NotNullTest();
|
||||
|
||||
$null->name = null;
|
||||
|
||||
$null->type = 1;
|
||||
try {
|
||||
$null->save();
|
||||
$this->fail();
|
||||
} catch(Doctrine_Exception $e) {
|
||||
$this->pass();
|
||||
}
|
||||
|
||||
}
|
||||
public function testGzipType() {
|
||||
$gzip = new GzipTest();
|
||||
$gzip->gzip = "compressed";
|
||||
|
@ -453,6 +453,12 @@ class Data_File extends Doctrine_Record {
|
||||
$this->hasOne("File_Owner", "Data_File.file_owner_id");
|
||||
}
|
||||
}
|
||||
class NotNullTest extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("name", "string", 100, "notnull");
|
||||
$this->hasColumn("type", "integer", 11);
|
||||
}
|
||||
}
|
||||
class File_Owner extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("name", "string", 255);
|
||||
|
Loading…
Reference in New Issue
Block a user