Commit 048d7788 authored by zYne's avatar zYne

Many-to-Many relation handling fixed, fixes #193

parent 7e4e5924
...@@ -145,128 +145,122 @@ class Doctrine_DataDict_Mysql extends Doctrine_DataDict { ...@@ -145,128 +145,122 @@ class Doctrine_DataDict_Mysql extends Doctrine_DataDict {
$type = array(); $type = array();
$unsigned = $fixed = null; $unsigned = $fixed = null;
switch ($db_type) { switch ($db_type) {
case 'tinyint': case 'tinyint':
$type[] = 'integer'; $type[] = 'integer';
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 1;
break;
case 'smallint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 2;
break;
case 'mediumint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 3;
break;
case 'int':
case 'integer':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 4;
break;
case 'bigint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 8;
break;
case 'tinytext':
case 'mediumtext':
case 'longtext':
case 'text':
case 'text':
case 'varchar':
$fixed = false;
case 'string':
case 'char':
$type[] = 'text';
if ($length == '1') {
$type[] = 'boolean'; $type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) { if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type); $type = array_reverse($type);
} }
} elseif (strstr($db_type, 'text')) { $unsigned = preg_match('/ unsigned/i', $field['type']);
$type[] = 'clob'; $length = 1;
if ($decimal == 'binary') {
$type[] = 'blob';
}
}
if ($fixed !== false) {
$fixed = true;
}
break; break;
case 'enum': case 'smallint':
$type[] = 'text'; $type[] = 'integer';
preg_match_all('/\'.+\'/U', $field['type'], $matches); $unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 0; $length = 2;
$fixed = false; break;
if (is_array($matches)) { case 'mediumint':
foreach ($matches[0] as $value) { $type[] = 'integer';
$length = max($length, strlen($value)-2); $unsigned = preg_match('/ unsigned/i', $field['type']);
} $length = 3;
if ($length == '1' && count($matches[0]) == 2) { break;
case 'int':
case 'integer':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 4;
break;
case 'bigint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 8;
break;
case 'tinytext':
case 'mediumtext':
case 'longtext':
case 'text':
case 'text':
case 'varchar':
$fixed = false;
case 'string':
case 'char':
$type[] = 'text';
if ($length == '1') {
$type[] = 'boolean'; $type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) { if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type); $type = array_reverse($type);
} }
} elseif (strstr($db_type, 'text')) {
$type[] = 'clob';
if ($decimal == 'binary') {
$type[] = 'blob';
}
}
if ($fixed !== false) {
$fixed = true;
} }
}
$type[] = 'integer';
case 'set':
$fixed = false;
$type[] = 'text';
$type[] = 'integer';
break; break;
case 'date': case 'enum':
$type[] = 'date'; $type[] = 'text';
$length = null; preg_match_all('/\'.+\'/U', $field['type'], $matches);
$length = 0;
$fixed = false;
if (is_array($matches)) {
foreach ($matches[0] as $value) {
$length = max($length, strlen($value)-2);
}
if ($length == '1' && count($matches[0]) == 2) {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
}
}
$type[] = 'integer';
case 'set':
$fixed = false;
$type[] = 'text';
$type[] = 'integer';
break; break;
case 'datetime': case 'date':
case 'timestamp': $type[] = 'date';
$type[] = 'timestamp'; $length = null;
$length = null;
break; break;
case 'time': case 'datetime':
$type[] = 'time'; case 'timestamp':
$length = null; $type[] = 'timestamp';
$length = null;
break; break;
case 'float': case 'time':
case 'double': $type[] = 'time';
case 'real': $length = null;
$type[] = 'float'; break;
$unsigned = preg_match('/ unsigned/i', $field['type']); case 'float':
case 'double':
case 'real':
$type[] = 'float';
$unsigned = preg_match('/ unsigned/i', $field['type']);
break; break;
case 'unknown': case 'unknown':
case 'decimal': case 'decimal':
case 'numeric': case 'numeric':
$type[] = 'decimal'; $type[] = 'decimal';
$unsigned = preg_match('/ unsigned/i', $field['type']); $unsigned = preg_match('/ unsigned/i', $field['type']);
break; break;
case 'tinyblob': case 'tinyblob':
case 'mediumblob': case 'mediumblob':
case 'longblob': case 'longblob':
case 'blob': case 'blob':
$type[] = 'blob'; $type[] = 'blob';
$length = null; $length = null;
break; break;
case 'year': case 'year':
$type[] = 'integer'; $type[] = 'integer';
$type[] = 'date'; $type[] = 'date';
$length = null; $length = null;
break; break;
default: default:
$db =& $this->getDBInstance(); throw new Doctrine_DataDict_Mysql_Exception('unknown database attribute type: '.$db_type);
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unknown database attribute type: '.$db_type, __FUNCTION__);
} }
return array($type, $length, $unsigned, $fixed); return array($type, $length, $unsigned, $fixed);
......
...@@ -126,7 +126,7 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict { ...@@ -126,7 +126,7 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict {
} }
$type = array(); $type = array();
$unsigned = $fixed = null; $unsigned = $fixed = null;
switch ($field['type']) { switch (strtolower($field['type'])) {
case 'smallint': case 'smallint':
case 'int2': case 'int2':
$type[] = 'integer'; $type[] = 'integer';
......
...@@ -847,11 +847,12 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -847,11 +847,12 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* this method is smart enough to know if any changes are made * this method is smart enough to know if any changes are made
* and whether to use INSERT or UPDATE statement * and whether to use INSERT or UPDATE statement
* *
* this method also saves the related composites * this method also saves the related components
* *
* @param Doctrine_Connection $conn
* @return void * @return void
*/ */
final public function save(Doctrine_Connection $conn = null) { public function save(Doctrine_Connection $conn = null) {
if ($conn === null) { if ($conn === null) {
$conn = $this->_table->getConnection(); $conn = $this->_table->getConnection();
} }
...@@ -885,7 +886,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -885,7 +886,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* returns an array of modified fields and associated values * returns an array of modified fields and associated values
* @return array * @return array
*/ */
final public function getModified() { public function getModified() {
$a = array(); $a = array();
foreach($this->_modified as $k => $v) { foreach($this->_modified as $k => $v) {
...@@ -1301,8 +1302,8 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -1301,8 +1302,8 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* @param string $fkField * @param string $fkField
* @return void * @return void
*/ */
final public function ownsOne($componentName,$foreignKey, $localKey = null) { final public function ownsOne($componentName, $foreignKey, $localKey = null) {
$this->_table->bind($componentName,$foreignKey,Doctrine_Relation::ONE_COMPOSITE, $localKey); $this->_table->bind($componentName, $foreignKey, Doctrine_Relation::ONE_COMPOSITE, $localKey);
} }
/** /**
* binds One-to-Many composite relation * binds One-to-Many composite relation
...@@ -1312,7 +1313,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -1312,7 +1313,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* @return void * @return void
*/ */
final public function ownsMany($componentName,$foreignKey, $localKey = null) { final public function ownsMany($componentName,$foreignKey, $localKey = null) {
$this->_table->bind($componentName,$foreignKey,Doctrine_Relation::MANY_COMPOSITE, $localKey); $this->_table->bind($componentName, $foreignKey, Doctrine_Relation::MANY_COMPOSITE, $localKey);
} }
/** /**
* binds One-to-One aggregate relation * binds One-to-One aggregate relation
...@@ -1322,7 +1323,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -1322,7 +1323,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* @return void * @return void
*/ */
final public function hasOne($componentName,$foreignKey, $localKey = null) { final public function hasOne($componentName,$foreignKey, $localKey = null) {
$this->_table->bind($componentName,$foreignKey,Doctrine_Relation::ONE_AGGREGATE, $localKey); $this->_table->bind($componentName, $foreignKey, Doctrine_Relation::ONE_AGGREGATE, $localKey);
} }
/** /**
* binds One-to-Many aggregate relation * binds One-to-Many aggregate relation
...@@ -1332,7 +1333,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -1332,7 +1333,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* @return void * @return void
*/ */
final public function hasMany($componentName,$foreignKey, $localKey = null) { final public function hasMany($componentName,$foreignKey, $localKey = null) {
$this->_table->bind($componentName,$foreignKey,Doctrine_Relation::MANY_AGGREGATE, $localKey); $this->_table->bind($componentName, $foreignKey, Doctrine_Relation::MANY_AGGREGATE, $localKey);
} }
/** /**
* setPrimaryKey * setPrimaryKey
......
...@@ -482,6 +482,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { ...@@ -482,6 +482,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable {
* @return array * @return array
*/ */
public function getBoundForName($name, $component) { public function getBoundForName($name, $component) {
foreach($this->bound as $k => $bound) { foreach($this->bound as $k => $bound) {
$e = explode('.', $bound[0]); $e = explode('.', $bound[0]);
...@@ -553,7 +554,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { ...@@ -553,7 +554,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable {
* @param string $field * @param string $field
* @return void * @return void
*/ */
final public function bind($name, $field, $type, $localKey) { public function bind($name, $field, $type, $localKey) {
if(isset($this->relations[$name])) if(isset($this->relations[$name]))
unset($this->relations[$name]); unset($this->relations[$name]);
...@@ -567,7 +568,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { ...@@ -567,7 +568,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable {
$alias = $name; $alias = $name;
$this->bound[$alias] = array($field,$type,$localKey,$name); $this->bound[$alias] = array($field, $type, $localKey, $name);
} }
/** /**
* getComponentName * getComponentName
...@@ -661,8 +662,12 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { ...@@ -661,8 +662,12 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable {
$bound = $table->getBoundForName($class, $component); $bound = $table->getBoundForName($class, $component);
break; break;
} catch(Doctrine_Table_Exception $exc) { } } catch(Doctrine_Table_Exception $exc) { }
} }
if( ! isset($bound))
throw new Doctrine_Table_Exception("Couldn't map many-to-many relation for "
. $this->options['name'] . " and $name. Components use different join tables.");
if( ! isset($local)) if( ! isset($local))
$local = $this->identifier; $local = $this->identifier;
...@@ -676,17 +681,17 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { ...@@ -676,17 +681,17 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable {
if(count($fields) > 1) { if(count($fields) > 1) {
// SELF-REFERENCING THROUGH JOIN TABLE // SELF-REFERENCING THROUGH JOIN TABLE
$this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($associationTable,$local,$fields[0],Doctrine_Relation::MANY_COMPOSITE, $e2[0]); $this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($associationTable, $local, $fields[0],Doctrine_Relation::MANY_COMPOSITE, $e2[0]);
$relation = new Doctrine_Relation_Association_Self($table,$associationTable,$fields[0],$fields[1], $type, $alias); $relation = new Doctrine_Relation_Association_Self($table, $associationTable, $fields[0], $fields[1], $type, $alias);
} else { } else {
// auto initialize a new one-to-one relationship for association table // auto initialize a new one-to-one relationship for association table
$associationTable->bind($this->getComponentName(), $associationTable->getComponentName(). '.' .$e2[1], Doctrine_Relation::ONE_AGGREGATE, 'id'); $associationTable->bind($this->getComponentName(), $associationTable->getComponentName(). '.' .$e2[1], Doctrine_Relation::ONE_AGGREGATE, $this->getIdentifier());
$associationTable->bind($table->getComponentName(), $associationTable->getComponentName(). '.' .$foreign, Doctrine_Relation::ONE_AGGREGATE, 'id'); $associationTable->bind($table->getComponentName(), $associationTable->getComponentName(). '.' .$foreign, Doctrine_Relation::ONE_AGGREGATE, $table->getIdentifier());
// NORMAL MANY-TO-MANY RELATIONSHIP // NORMAL MANY-TO-MANY RELATIONSHIP
$this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($associationTable,$local,$e2[1],Doctrine_Relation::MANY_COMPOSITE, $e2[0]); $this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($associationTable, $local, $e2[1], Doctrine_Relation::MANY_COMPOSITE, $e2[0]);
$relation = new Doctrine_Relation_Association($table, $associationTable, $e2[1], $foreign, $type, $alias); $relation = new Doctrine_Relation_Association($table, $associationTable, $e2[1], $foreign, $type, $alias);
} }
......
...@@ -83,7 +83,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase { ...@@ -83,7 +83,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
public function testLimitWithOneToManyInnerJoin() { public function testLimitWithOneToManyInnerJoin() {
$this->query->from("User(id):Phonenumber"); $this->query->select('u.id')->from("User u INNER JOIN u.Phonenumber");
$this->query->limit(5); $this->query->limit(5);
...@@ -177,7 +177,8 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase { ...@@ -177,7 +177,8 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$q = new Doctrine_Query(); $q = new Doctrine_Query();
$q->from("User")->where("User.Group.id = ?")->orderby("User.id DESC")->limit(5); $q->from("User")->where("User.Group.id = ?")->orderby("User.id ASC")->limit(5);
$users = $q->execute(array($user->Group[1]->id)); $users = $q->execute(array($user->Group[1]->id));
$this->assertEqual($users->count(), 3); $this->assertEqual($users->count(), 3);
...@@ -222,7 +223,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase { ...@@ -222,7 +223,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$photos = $q->execute(array(1)); $photos = $q->execute(array(1));
$this->assertEqual($photos->count(), 3); $this->assertEqual($photos->count(), 3);
$this->assertEqual($q->getQuery(), $this->assertEqual($q->getQuery(),
"SELECT photo.id AS photo__id, photo.name AS photo__name FROM photo LEFT JOIN phototag ON photo.id = phototag.photo_id LEFT JOIN tag ON tag.id = phototag.tag_id WHERE photo.id IN (SELECT DISTINCT photo.id FROM photo LEFT JOIN phototag ON photo.id = phototag.photo_id LEFT JOIN tag ON tag.id = phototag.tag_id WHERE tag.id = ? LIMIT 100) AND tag.id = ? ORDER BY photo.id DESC"); "SELECT photo.id AS photo__id, photo.name AS photo__name FROM photo LEFT JOIN phototag ON photo.id = phototag.photo_id LEFT JOIN tag ON tag.id = phototag.tag_id WHERE photo.id IN (SELECT DISTINCT photo.id FROM photo LEFT JOIN phototag ON photo.id = phototag.photo_id LEFT JOIN tag ON tag.id = phototag.tag_id WHERE tag.id = ? ORDER BY photo.id DESC LIMIT 100) AND tag.id = ? ORDER BY photo.id DESC");
} }
} }
?> ?>
...@@ -10,9 +10,40 @@ class M2MTest extends Doctrine_Record { ...@@ -10,9 +10,40 @@ class M2MTest extends Doctrine_Record {
$this->hasMany('RTC2 as RTC2', 'JC1.c1_id'); $this->hasMany('RTC2 as RTC2', 'JC1.c1_id');
$this->hasMany('RTC3 as RTC3', 'JC2.c1_id'); $this->hasMany('RTC3 as RTC3', 'JC2.c1_id');
$this->hasMany('RTC3 as RTC4', 'JC1.c1_id'); $this->hasMany('RTC3 as RTC4', 'JC1.c1_id');
}
}
class RelationErrorTest extends Doctrine_Record {
public function setTableDefinition() {
$this->hasColumn('name', 'string', 200);
}
public function setUp() {
$this->hasMany('RTCUnknown', 'JC1.c1_id');
}
}
class M2MTest2 extends Doctrine_Record {
public function setTableDefinition() {
$this->hasColumn('oid', 'integer', 11, array('autoincrement', 'primary'));
$this->hasColumn('name', 'string', 20);
}
public function setUp() {
$this->hasMany('RTC4 as RTC5', 'JC3.c1_id');
}
}
class RTCUnknown extends Doctrine_Record {
public function setTableDefinition() {
$this->hasColumn('name', 'string', 200);
}
public function setUp() {
$this->hasMany('M2MTest', 'JC2.c2_id');
}
}
class JC3 extends Doctrine_Record {
public function setTableDefinition() {
$this->hasColumn('c1_id', 'integer');
$this->hasColumn('c2_id', 'integer');
} }
} }
class JC1 extends Doctrine_Record { class JC1 extends Doctrine_Record {
public function setTableDefinition() { public function setTableDefinition() {
$this->hasColumn('c1_id', 'integer'); $this->hasColumn('c1_id', 'integer');
...@@ -50,12 +81,105 @@ class RTC3 extends Doctrine_Record { ...@@ -50,12 +81,105 @@ class RTC3 extends Doctrine_Record {
$this->hasMany('M2MTest as RTC4', 'JC1.c2_id'); $this->hasMany('M2MTest as RTC4', 'JC1.c2_id');
} }
} }
class RTC4 extends Doctrine_Record {
public function setTableDefinition() {
$this->hasColumn('oid', 'integer', 11, array('autoincrement', 'primary'));
$this->hasColumn('name', 'string', 20);
}
public function setUp() {
$this->hasMany('M2MTest2', 'JC3.c2_id');
}
}
class Doctrine_Relation_ManyToMany_TestCase extends Doctrine_UnitTestCase { class Doctrine_Relation_ManyToMany_TestCase extends Doctrine_UnitTestCase {
public function prepareData() { } public function prepareData() { }
public function prepareTables() { public function prepareTables() {
parent::prepareTables(); parent::prepareTables();
} }
public function testManyToManyRelationWithAliasesAndCustomPKs() {
$component = new M2MTest2();
try {
$rel = $component->getTable()->getRelation('RTC5');
$this->pass();
} catch(Doctrine_Exception $e) {
$this->fail();
}
$this->assertTrue($rel instanceof Doctrine_Relation_Association);
$this->assertTrue($component->RTC5 instanceof Doctrine_Collection);
try {
$rel = $component->getTable()->getRelation('JC3');
$this->pass();
} catch(Doctrine_Exception $e) {
$this->fail();
}
$this->assertEqual($rel->getLocal(), 'oid');
}
public function testJoinComponent() {
$component = new JC3();
try {
$rel = $component->getTable()->getRelation('M2MTest2');
$this->pass();
} catch(Doctrine_Exception $e) {
$this->fail();
}
$this->assertEqual($rel->getForeign(), 'oid');
try {
$rel = $component->getTable()->getRelation('RTC4');
$this->pass();
} catch(Doctrine_Exception $e) {
$this->fail();
}
$this->assertEqual($rel->getForeign(), 'oid');
}
public function testManyToManyRelationFetchingWithAliasesAndCustomPKs() {
$q = new Doctrine_Query();
try {
$q->from('M2MTest2 m LEFT JOIN m.RTC5');
$this->pass();
} catch(Doctrine_Exception $e) {
$this->fail();
}
try {
$q->execute();
$this->pass();
} catch(Doctrine_Exception $e) {
$this->fail();
}
}
public function testUnknownManyToManyRelation() {
$component = new RelationErrorTest();
try {
$rel = $component->getTable()->getRelation('RTCUnknown');
$this->fail();
} catch(Doctrine_Table_Exception $e) {
$this->pass();
}
}
public function testManyToManyRelationFetchingWithAliasesAndCustomPKs2() {
$q = new Doctrine_Query();
try {
$q->from('M2MTest2 m INNER JOIN m.JC3');
$this->pass();
} catch(Doctrine_Exception $e) {
$this->fail();
}
try {
$q->execute();
$this->pass();
} catch(Doctrine_Exception $e) {
$this->fail();
}
}
public function testManyToManyHasRelationWithAliases4() { public function testManyToManyHasRelationWithAliases4() {
$component = new M2MTest(); $component = new M2MTest();
......
...@@ -66,10 +66,12 @@ $test = new GroupTest('Doctrine Framework Unit Tests'); ...@@ -66,10 +66,12 @@ $test = new GroupTest('Doctrine Framework Unit Tests');
$test->addTestCase(new Doctrine_DataDict_Pgsql_TestCase()); $test->addTestCase(new Doctrine_DataDict_Pgsql_TestCase());
$test->addTestCase(new Doctrine_Relation_TestCase());
$test->addTestCase(new Doctrine_Relation_ManyToMany_TestCase()); $test->addTestCase(new Doctrine_Relation_ManyToMany_TestCase());
$test->addTestCase(new Doctrine_Relation_TestCase());
$test->addTestCase(new Doctrine_Record_TestCase()); $test->addTestCase(new Doctrine_Record_TestCase());
$test->addTestCase(new Doctrine_Record_State_TestCase()); $test->addTestCase(new Doctrine_Record_State_TestCase());
...@@ -148,7 +150,6 @@ $test->addTestCase(new Doctrine_Query_Delete_TestCase()); ...@@ -148,7 +150,6 @@ $test->addTestCase(new Doctrine_Query_Delete_TestCase());
$test->addTestCase(new Doctrine_Query_Update_TestCase()); $test->addTestCase(new Doctrine_Query_Update_TestCase());
$test->addTestCase(new Doctrine_Query_Limit_TestCase()); $test->addTestCase(new Doctrine_Query_Limit_TestCase());
$test->addTestCase(new Doctrine_EnumTestCase()); $test->addTestCase(new Doctrine_EnumTestCase());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment