Commit c9e345d4 authored by doctrine's avatar doctrine

Preliminary support for join table self-referencing

parent 90d34063
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
* thrown when user tries to get a foreign key object but the mapping is not done right * thrown when user tries to get a foreign key object but the mapping is not done right
*/ */
class Doctrine_Mapping_Exception extends Doctrine_Exception { class Doctrine_Mapping_Exception extends Doctrine_Exception {
public function __construct() { public function __construct($message = "An error occured in the mapping logic.") {
parent::__construct("An error occured in the mapping logic.",Doctrine::ERR_MAPPING); parent::__construct($message,Doctrine::ERR_MAPPING);
} }
} }
?> ?>
...@@ -319,10 +319,17 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -319,10 +319,17 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* @return boolean * @return boolean
*/ */
final public function refresh() { final public function refresh() {
if($this->getID() == null) return false; $id = $this->getID();
if( ! is_array($id))
$id = array($id);
if(empty($id))
return false;
$id = array_values($id);
$query = $this->table->getQuery()." WHERE ".implode(" = ? && ",$this->table->getPrimaryKeys())." = ?"; $query = $this->table->getQuery()." WHERE ".implode(" = ? && ",$this->table->getPrimaryKeys())." = ?";
$this->data = $this->table->getSession()->execute($query,array($this->getID()))->fetch(PDO::FETCH_ASSOC); $this->data = $this->table->getSession()->execute($query,$id)->fetch(PDO::FETCH_ASSOC);
$this->modified = array(); $this->modified = array();
$this->cleanData(); $this->cleanData();
......
...@@ -333,8 +333,9 @@ abstract class Doctrine_Session extends Doctrine_Configurable implements Countab ...@@ -333,8 +333,9 @@ abstract class Doctrine_Session extends Doctrine_Configurable implements Countab
* @return void * @return void
*/ */
public function clear() { public function clear() {
foreach($this->tables as $k => $objTable) { foreach($this->tables as $k => $table) {
$objTable->getRepository()->evictAll(); $table->getRepository()->evictAll();
$table->clear();
} }
$this->tables = array(); $this->tables = array();
} }
......
...@@ -451,9 +451,7 @@ class Doctrine_Table extends Doctrine_Configurable { ...@@ -451,9 +451,7 @@ class Doctrine_Table extends Doctrine_Configurable {
if(isset($this->bound[$name])) { if(isset($this->bound[$name])) {
$type = $this->bound[$name][1]; $type = $this->bound[$name][1];
$local = $this->bound[$name][2]; $local = $this->bound[$name][2];
$e = explode(".",$this->bound[$name][0]); list($component, $foreign) = explode(".",$this->bound[$name][0]);
$component = $e[0];
$foreign = $e[1];
$alias = $name; $alias = $name;
$name = $this->bound[$alias][3]; $name = $this->bound[$alias][3];
...@@ -469,7 +467,7 @@ class Doctrine_Table extends Doctrine_Configurable { ...@@ -469,7 +467,7 @@ class Doctrine_Table extends Doctrine_Configurable {
$relation = new Doctrine_LocalKey($table,$foreign,$local,$type); $relation = new Doctrine_LocalKey($table,$foreign,$local,$type);
} else } else
throw new Doctrine_Mapping_Exception(); throw new Doctrine_Mapping_Exception("Only one-to-one relations are possible when local reference key is used.");
} elseif($component == $name || ($component == $alias && $name == $this->name)) { } elseif($component == $name || ($component == $alias && $name == $this->name)) {
if( ! isset($local)) if( ! isset($local))
...@@ -483,31 +481,39 @@ class Doctrine_Table extends Doctrine_Configurable { ...@@ -483,31 +481,39 @@ class Doctrine_Table extends Doctrine_Configurable {
// only aggregate relations allowed // only aggregate relations allowed
if($type != Doctrine_Relation::MANY_AGGREGATE) if($type != Doctrine_Relation::MANY_AGGREGATE)
throw new Doctrine_Mapping_Exception(); throw new Doctrine_Mapping_Exception("Only aggregate relations are allowed for many-to-many relations");
$classes = array_merge($this->parents, array($this->name)); $classes = array_merge($this->parents, array($this->name));
foreach($classes as $class) { foreach(array_reverse($classes) as $class) {
try { try {
$bound = $table->getBoundForName($class); $bound = $table->getBoundForName($class);
break; break;
} catch(InvalidKeyException $exc) { } catch(InvalidKeyException $exc) { }
}
} }
if( ! isset($local)) if( ! isset($local))
$local = $this->identifier; $local = $this->identifier;
$e2 = explode(".",$bound[0]); $e2 = explode(".",$bound[0]);
$fields = explode("-",$e2[1]);
if($e2[0] != $component) if($e2[0] != $component)
throw new Doctrine_Mapping_Exception(); throw new Doctrine_Mapping_Exception($e2[0]." doesn't match ".$component);
$associationTable = $this->session->getTable($e2[0]); $associationTable = $this->session->getTable($e2[0]);
$this->relations[$e2[0]] = new Doctrine_ForeignKey($associationTable,$local,$e2[1],Doctrine_Relation::MANY_COMPOSITE); if(count($fields) > 1) {
// SELF-REFERENCING THROUGH JOIN TABLE
$this->relations[$e2[0]] = new Doctrine_ForeignKey($associationTable,$local,$fields[0],Doctrine_Relation::MANY_COMPOSITE);
$relation = new Doctrine_Association($table,$associationTable,$fields[0],$fields[1],$type);
} else {
// NORMAL MANY-TO-MANY RELATIONSHIP
$this->relations[$e2[0]] = new Doctrine_ForeignKey($associationTable,$local,$e2[1],Doctrine_Relation::MANY_COMPOSITE);
$relation = new Doctrine_Association($table,$associationTable,$e2[1],$foreign,$type); $relation = new Doctrine_Association($table,$associationTable,$e2[1],$foreign,$type);
}
} }
$this->relations[$alias] = $relation; $this->relations[$alias] = $relation;
......
...@@ -2,6 +2,52 @@ ...@@ -2,6 +2,52 @@
require_once("UnitTestCase.class.php"); require_once("UnitTestCase.class.php");
class Doctrine_RecordTestCase extends Doctrine_UnitTestCase { class Doctrine_RecordTestCase extends Doctrine_UnitTestCase {
public function testJoinTableSelfReferencing() {
$e = new Entity();
$e->name = "Entity test";
$this->assertTrue($e->Entity[0] instanceof Entity);
$this->assertTrue($e->Entity[1] instanceof Entity);
$this->assertEqual($e->Entity[0]->getState(), Doctrine_Record::STATE_TCLEAN);
$this->assertEqual($e->Entity[1]->getState(), Doctrine_Record::STATE_TCLEAN);
$e->Entity[0]->name = "Subentity 1";
$e->Entity[1]->name = "Subentity 2";
$this->assertEqual($e->Entity[0]->name, "Subentity 1");
$this->assertEqual($e->Entity[1]->name, "Subentity 2");
$this->assertEqual($e->Entity[0]->getState(), Doctrine_Record::STATE_TDIRTY);
$this->assertEqual($e->Entity[1]->getState(), Doctrine_Record::STATE_TDIRTY);
$e->save();
$this->assertTrue($e->Entity[0] instanceof Entity);
$this->assertTrue($e->Entity[1] instanceof Entity);
$this->assertEqual($e->Entity[0]->name, "Subentity 1");
$this->assertEqual($e->Entity[1]->name, "Subentity 2");
$this->assertEqual($e->Entity[0]->getState(), Doctrine_Record::STATE_CLEAN);
$this->assertEqual($e->Entity[1]->getState(), Doctrine_Record::STATE_CLEAN);
$e = $e->getTable()->find($e->getID());
$this->assertTrue($e->Entity[0] instanceof Entity);
$this->assertTrue($e->Entity[1] instanceof Entity);
$this->assertEqual($e->Entity[0]->name, "Subentity 1");
$this->assertEqual($e->Entity[1]->name, "Subentity 2");
$this->assertEqual($e->Entity[0]->getState(), Doctrine_Record::STATE_CLEAN);
$this->assertEqual($e->Entity[1]->getState(), Doctrine_Record::STATE_CLEAN);
$coll = $this->session->query("FROM Entity WHERE Entity.name = 'Subentity 1'");
$this->assertEqual($coll->count(), 1);
$this->assertEqual($coll[0]->getState(), Doctrine_Record::STATE_CLEAN);
$this->assertEqual($coll[0]->name, "Subentity 1");
}
public function testCompositePK() { public function testCompositePK() {
$record = new EntityReference(); $record = new EntityReference();
...@@ -48,6 +94,26 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase { ...@@ -48,6 +94,26 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase {
$this->assertEqual($record->entity2, 5); $this->assertEqual($record->entity2, 5);
$this->assertEqual($record->entity1, 2); $this->assertEqual($record->entity1, 2);
$this->assertEqual($record->getID(), array("entity1" => 2, "entity2" => 5)); $this->assertEqual($record->getID(), array("entity1" => 2, "entity2" => 5));
$record->refresh();
$this->assertEqual($record->getState(), Doctrine_Record::STATE_CLEAN);
$this->assertEqual($record->entity2, 5);
$this->assertEqual($record->entity1, 2);
$this->assertEqual($record->getID(), array("entity1" => 2, "entity2" => 5));
$record = new EntityReference();
$record->entity2 = 6;
$record->entity1 = 2;
$record->save();
$coll = $this->session->query("FROM EntityReference-b");
$this->assertTrue($coll[0] instanceof EntityReference);
$this->assertEqual($coll[0]->getState(), Doctrine_Record::STATE_CLEAN);
$this->assertTrue($coll[1] instanceof EntityReference);
$this->assertEqual($coll[1]->getState(), Doctrine_Record::STATE_CLEAN);
$coll = $this->session->query("FROM EntityReference-b WHERE EntityReference.entity2 = 5");
$this->assertEqual($coll->count(), 1);
} }
...@@ -605,6 +671,5 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase { ...@@ -605,6 +671,5 @@ class Doctrine_RecordTestCase extends Doctrine_UnitTestCase {
$user = $this->session->getTable("User")->find(4); $user = $this->session->getTable("User")->find(4);
$this->assertTrue($user->getIterator() instanceof ArrayIterator); $this->assertTrue($user->getIterator() instanceof ArrayIterator);
} }
} }
?> ?>
...@@ -4,6 +4,7 @@ class Entity extends Doctrine_Record { ...@@ -4,6 +4,7 @@ class Entity extends Doctrine_Record {
$this->ownsOne("Email","Entity.email_id"); $this->ownsOne("Email","Entity.email_id");
$this->ownsMany("Phonenumber","Phonenumber.entity_id"); $this->ownsMany("Phonenumber","Phonenumber.entity_id");
$this->ownsOne("Account","Account.entity_id"); $this->ownsOne("Account","Account.entity_id");
$this->hasMany("Entity","EntityReference.entity1-entity2");
} }
public function setTableDefinition() { public function setTableDefinition() {
$this->hasColumn("id","integer",20,"autoincrement|primary"); $this->hasColumn("id","integer",20,"autoincrement|primary");
......
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