Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
Index: tests/run.php =================================================================== --- tests/run.php (revision 4799) +++ tests/run.php (working copy) @@ -118,6 +118,7 @@ $tickets->addTestCase(new Doctrine_Ticket_1296_TestCase()); $tickets->addTestCase(new Doctrine_Ticket_1304_TestCase()); $tickets->addTestCase(new Doctrine_Ticket_1305_TestCase()); +$tickets->addTestCase(new Doctrine_Ticket_1323_TestCase()); $test->addTestCase($tickets); // Connection Tests (not yet fully tested) Index: tests/Relation/ManyToManyTestCase.php =================================================================== --- tests/Relation/ManyToManyTestCase.php (revision 4799) +++ tests/Relation/ManyToManyTestCase.php (working copy) @@ -35,6 +35,7 @@ $rel = $component->getTable()->getRelation('M2MTest2'); $this->pass(); } catch(Doctrine_Exception $e) { + echo $e->getMessage(); $this->fail(); } $this->assertEqual($rel->getForeign(), 'oid'); Index: tests/Ticket/1323TestCase.php =================================================================== --- tests/Ticket/1323TestCase.php (revision 0) +++ tests/Ticket/1323TestCase.php (revision 0) @@ -0,0 +1,225 @@ +<?php + +class Doctrine_Ticket_1323_TestCase extends Doctrine_UnitTestCase { + public function prepareTables() { + $this->tables = array(); + $this->tables[] = "T1323User"; + $this->tables[] = "T1323UserReference"; + parent::prepareTables(); + } + + public function prepareData() {} + + public function resetData() + { + $q = Doctrine_Query::create(); + $q->delete()->from("T1323UserReference")->execute(); + $q = Doctrine_Query::create(); + $q->delete()->from("T1323User")->execute(); + + $m = new T1323User(); + $m->name = "Mother"; + $m->save(); + $f = new T1323User(); + $f->name = "Father"; + $f->save(); + $s = new T1323User(); + $s->name = "Son"; + $s->save(); + $d = new T1323User(); + $d->name = "Daughter"; + $d->save(); + $gf = new T1323User(); + $gf->name = "Grandfather"; + $gf->save(); + $gm = new T1323User(); + $gm->name = "Grandmother"; + $gm->save(); + + $f->Children[] = $s; + $f->Children[] = $d; + + $f->Parents[] = $gf; + $f->Parents[] = $gm; + + $f->save(); + + $m->Children[] = $s; + $m->Children[] = $d; + + $m->save(); + + } + + public function testRelationsAreCorrect() { + $this->resetData(); + + $f = Doctrine::getTable("T1323User")->findOneByName("Father"); + $childLinks = $f->childLinks; + $this->assertEqual(2, count($childLinks)); + $this->assertEqual($f->id, $childLinks[0]->parent_id); + $this->assertEqual($f->id, $childLinks[1]->parent_id); + + $parentLinks = $f->parentLinks; + $this->assertEqual(2, count($parentLinks)); + $this->assertEqual($f->id, $parentLinks[0]->child_id); + $this->assertEqual($f->id, $parentLinks[1]->child_id); + + $m = Doctrine::getTable("T1323User")->findOneByName("Mother"); + $childLinks = $m->childLinks; + $this->assertEqual(2, count($childLinks)); + $this->assertEqual($m->id, $childLinks[0]->parent_id); + $this->assertEqual($m->id, $childLinks[1]->parent_id); + + $parentLinks = $m->parentLinks; + $this->assertEqual(0, count($parentLinks)); + + $s = Doctrine::getTable("T1323User")->findOneByName("Son"); + $childLinks = $s->childLinks; + $this->assertEqual(0, count($childLinks)); + $parentLinks = $s->parentLinks; + $this->assertEqual(2, count($parentLinks)); + $this->assertEqual($s->id, $parentLinks[0]->child_id); + $this->assertEqual($s->id, $parentLinks[1]->child_id); + + $d = Doctrine::getTable("T1323User")->findOneByName("Daughter"); + $childLinks = $d->childLinks; + $this->assertEqual(0, count($childLinks)); + $parentLinks = $d->parentLinks; + $this->assertEqual(2, count($parentLinks)); + $this->assertEqual($d->id, $parentLinks[0]->child_id); + $this->assertEqual($d->id, $parentLinks[1]->child_id); + + $gm = Doctrine::getTable("T1323User")->findOneByName("Grandmother"); + $childLinks = $gm->childLinks; + $this->assertEqual(1, count($childLinks)); + $this->assertEqual($gm->id, $childLinks[0]->parent_id); + $parentLinks = $gm->parentLinks; + $this->assertEqual(0, count($parentLinks)); + + $gf = Doctrine::getTable("T1323User")->findOneByName("Grandfather"); + $childLinks = $gf->childLinks; + $this->assertEqual(1, count($childLinks)); + $this->assertEqual($gf->id, $childLinks[0]->parent_id); + $parentLinks = $gf->parentLinks; + $this->assertEqual(0, count($parentLinks)); + } + + /** + * this test will fail + */ + public function testWithShow() { + $this->resetData(); + + T1323User::showAllRelations(); + $this->runTests(); + } + + /** + * this test will pass + */ + public function testWithoutShow() { + $this->resetData(); + + $this->runTests(); + } + + + public function runTests() { + + // change "Father"'s name... + $f = Doctrine::getTable("T1323User")->findOneByName("Father"); + $f->name = "Dad"; + $f->save(); + + /* just playing; makes no difference: + remove "Dad"'s relation to "Son"... */ + //$s = Doctrine::getTable("T1323User")->findOneByName("Son"); + //$f->unlink("Children", array($s->id)); + //$f->save(); + + $relations = Doctrine::getTable("T1323UserReference")->findAll(); + foreach ($relations as $relation) { + /* never directly touched any relation; so no user should have + himself as parent or child */ + $this->assertNotEqual($relation->parent_id, $relation->child_id); + } + } +} + + + +class T1323User extends Doctrine_Record +{ + public function setTableDefinition() + { + $this->hasColumn('name', 'string', 30); + } + + public function setUp() + { + $this->hasMany('T1323User as Parents', array('local' => 'child_id', + 'foreign' => 'parent_id', + 'refClass' => 'T1323UserReference', + 'refClassRelation' => 'childLinks' + )); + + $this->hasMany('T1323User as Children', array('local' => 'parent_id', + 'foreign' => 'child_id', + 'refClass' => 'T1323UserReference', + 'refClassRelation' => 'parentLinks' + )); + } + + /** + * just a little function to show all users and their relations + */ + public static function showAllRelations() { + $users = Doctrine::getTable("T1323User")->findAll(); + + //echo "=========================================<br/>".PHP_EOL; + //echo "list of all existing users and their relations:<br/> ".PHP_EOL; + //echo "=========================================<br/><br/>".PHP_EOL.PHP_EOL; + + foreach ($users as $user) { + $parents = $user->Parents; + $children = $user->Children; + + /*echo "user: "; + echo $user->name; + echo PHP_EOL."<br/>"; + + echo "parents:"; + echo PHP_EOL."<br/>"; + foreach ($parents as $parent) { + echo $parent->name; + echo PHP_EOL."<br/>"; + } + echo PHP_EOL."<br/>"; + + echo "children:"; + echo PHP_EOL."<br/>"; + foreach ($children as $child) { + echo $child->name; + echo PHP_EOL."<br/>"; + } + echo PHP_EOL."<br/>"; + echo "--------------".PHP_EOL."<br/>"; + echo PHP_EOL."<br/>";*/ + } + } +} + +class T1323UserReference extends Doctrine_Record +{ + public function setTableDefinition() + { + //$this->hasColumn('id', 'integer', null, array('primary' => true, 'autoincrement' => true)); + $this->hasColumn('parent_id', 'integer', null, array('primary' => true)); + $this->hasColumn('child_id', 'integer', null, array('primary' => true)); + } +} + + + +?> Index: lib/Doctrine/Relation.php =================================================================== --- lib/Doctrine/Relation.php (revision 4799) +++ lib/Doctrine/Relation.php (working copy) @@ -79,6 +79,7 @@ 'equal' => false, 'cascade' => array(), // application-level cascades 'owningSide' => false, // whether this is the owning side + 'refClassRelation' => null, ); /** Index: lib/Doctrine/Relation/Nest.php =================================================================== --- lib/Doctrine/Relation/Nest.php (revision 4799) +++ lib/Doctrine/Relation/Nest.php (working copy) @@ -38,7 +38,7 @@ * @param integer $count * @return string */ - public function getRelationDql($count, $context = 'record') + /*public function getRelationDql($count, $context = 'record') { switch ($context) { case 'record': @@ -72,9 +72,8 @@ }; return $dql; - } + }*/ - /** public function fetchRelatedFor(Doctrine_Record $record) { $id = $record->getIncremented(); @@ -82,32 +81,6 @@ if (empty($id) || ! $this->definition['table']->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) { return new Doctrine_Collection($this->getTable()); } else { - $q = new Doctrine_Query(); - - $c = $this->getTable()->getComponentName(); - $a = substr($c, 0, 1); - $c2 = $this->getAssociationTable()->getComponentName(); - $a2 = substr($c2, 0, 1); - - $q->from($c) - ->innerJoin($c . '.' . $c2) - - $sub = 'SELECT ' . $this->getForeign() - . ' FROM ' . $c2 - . ' WHERE ' . $this->getLocal() - . ' = ?'; - } - } - */ - - public function fetchRelatedFor(Doctrine_Record $record) - { - $id = $record->getIncremented(); - - - if (empty($id) || ! $this->definition['table']->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) { - return new Doctrine_Collection($this->getTable()); - } else { $q = new Doctrine_RawSql($this->getTable()->getConnection()); $assocTable = $this->getAssociationFactory()->getTableName(); @@ -136,11 +109,17 @@ ->from($tableName . ' INNER JOIN ' . $assocTable . ' ON ' . implode(' OR ', $joinCondition)) ->where(implode(' OR ', $condition)); $q->addComponent($tableName, $record->getTable()->getComponentName()); - $q->addComponent($assocTable, $record->getTable()->getComponentName(). '.' . $this->getAssociationFactory()->getComponentName()); + + $path = $record->getTable()->getComponentName(). '.' . $this->getAssociationFactory()->getComponentName(); + if ($this->definition['refClassRelation']) { + $path = $record->getTable()->getComponentName(). '.' . $this->definition['refClassRelation']; + } + $q->addComponent($assocTable, $path); $params = ($this->definition['equal']) ? array($id, $id) : array($id); + $res = $q->execute($params); - return $q->execute($params); + return $res; } } } \ No newline at end of file Index: lib/Doctrine/Relation/Parser.php =================================================================== --- lib/Doctrine/Relation/Parser.php (revision 4799) +++ lib/Doctrine/Relation/Parser.php (working copy) @@ -155,22 +155,24 @@ if (isset($this->_relations[$alias])) { return $this->_relations[$alias]; } - + if (isset($this->_pending[$alias])) { $def = $this->_pending[$alias]; $identifierColumnNames = $this->_table->getIdentifierColumnNames(); $idColumnName = array_pop($identifierColumnNames); - + // check if reference class name exists // if it does we are dealing with association relation if (isset($def['refClass'])) { $def = $this->completeAssocDefinition($def); $localClasses = array_merge($this->_table->getOption('parents'), array($this->_table->getComponentName())); + + $backRefRelationName = isset($def['refClassRelation']) ? + $def['refClassRelation'] : $def['refClass']; + if ( ! isset($this->_pending[$backRefRelationName]) && ! isset($this->_relations[$backRefRelationName])) { - if ( ! isset($this->_pending[$def['refClass']]) && - ! isset($this->_relations[$def['refClass']])) { - $parser = $def['refTable']->getRelationParser(); + if ( ! $parser->hasRelation($this->_table->getComponentName())) { $parser->bind($this->_table->getComponentName(), array('type' => Doctrine_Relation::ONE, @@ -180,10 +182,18 @@ )); } - if ( ! $this->hasRelation($def['refClass'])) { - $this->bind($def['refClass'], array('type' => Doctrine_Relation::MANY, - 'foreign' => $def['local'], - 'local' => $idColumnName)); + if ( ! $this->hasRelation($backRefRelationName)) { + if (in_array($def['class'], $localClasses)) { + $this->bind($def['refClass'] . " as " . $backRefRelationName, array( + 'type' => Doctrine_Relation::MANY, + 'foreign' => $def['foreign'], + 'local' => $idColumnName)); + } else { + $this->bind($def['refClass'] . " as " . $backRefRelationName, array( + 'type' => Doctrine_Relation::MANY, + 'foreign' => $def['local'], + 'local' => $idColumnName)); + } } } if (in_array($def['class'], $localClasses)) { @@ -212,7 +222,6 @@ if (isset($rel)) { // unset pending relation unset($this->_pending[$alias]); - $this->_relations[$alias] = $rel; return $rel; } @@ -292,7 +301,6 @@ if ( ! isset($def['local'])) { // foreign key not set // try to guess the foreign key - $def['local'] = ($def['foreign'] === $id[0]) ? $id[1] : $id[0]; } } else { Index: lib/Doctrine/Collection.php =================================================================== --- lib/Doctrine/Collection.php (revision 4799) +++ lib/Doctrine/Collection.php (working copy) @@ -263,8 +263,7 @@ $this->relation = $relation; if ($relation instanceof Doctrine_Relation_ForeignKey || - $relation instanceof Doctrine_Relation_LocalKey) { - + $relation instanceof Doctrine_Relation_LocalKey) { $this->referenceField = $relation->getForeignFieldName(); $value = $record->get($relation->getLocalFieldName()); @@ -441,7 +440,6 @@ { if (isset($this->referenceField)) { $value = $this->reference->get($this->relation->getLocalFieldName()); - if ($value !== null) { $record->set($this->referenceField, $value, false); } else { Index: lib/Doctrine/Record.php =================================================================== --- lib/Doctrine/Record.php (revision 4799) +++ lib/Doctrine/Record.php (working copy) @@ -958,7 +958,7 @@ $old = $this->_data[$fieldName]; } - if ($this->_isValueModified($type, $old, $value)) { + if ($this->_isValueModified($type, $old, $value)) { if ($value === null) { $default = $this->_table->getDefaultValueOf($fieldName); $value = ($default === null) ? self::$_null : $default; @@ -1142,7 +1142,7 @@ * @return void */ public function save(Doctrine_Connection $conn = null) - { + { if ($conn === null) { $conn = $this->_table->getConnection(); }
This paste will be private.
From the Design Piracy series on my blog: