Permalink
Browse files

Merge pull request #90 from jaugustin/refactor-get-many-to-many

Propel Generator: for getManyToManyTables use real ManyToMany, fixes #88,
  • Loading branch information...
2 parents b3c15ff + d84cb02 commit cc91e668ff9a47382e5f59ad2a0138c7577a2d41 @willdurand willdurand committed Mar 11, 2012
@@ -124,35 +124,48 @@ public function generate($params = array())
public function getManyToManyTables()
{
$tables = array();
+ $foreignTables = array();
+ $relations = array();
- // go through all tables to find m2m relationships
- foreach ($this->dbMap->getTables() as $tableName => $table)
+ // go through all relations
+ foreach ($this->table->getRelations() as $relation)
+ {
+ //we have a many to many Relation
+ if (RelationMap::MANY_TO_MANY === $relation->getType())
+ {
+ $foreignTables[$relation->getLocalTable()->getClassname()] = $relation->getLocalTable();
+ }
+ else if (RelationMap::ONE_TO_MANY === $relation->getType())
+ {
+ $relations[$relation->getLocalTable()->getClassname()] = $relation;
+ }
+ }
+
+ // find middleTable for Many to Many relation
+ foreach ($foreignTables as $tableName => $foreignTable)
{
- foreach ($table->getColumns() as $column)
+ foreach ($foreignTable->getRelations() as $foreignRelation)
{
- if ($column->isForeignKey() && $column->isPrimaryKey() && $this->table->getClassname() == $this->getForeignTable($column)->getClassname())
+ $foreignTableName = $foreignRelation->getLocalTable()->getClassname();
+
+ // Test if the foreign table has a common relation with our table
+ // TODO: test if is CrossRef
+ if (RelationMap::ONE_TO_MANY === $foreignRelation->getType()
+ && array_key_exists($foreignTableName, $relations))
{
- // we have a m2m relationship
- // find the other primary key
- foreach ($table->getColumns() as $relatedColumn)
- {
- if ($relatedColumn->isForeignKey() && $relatedColumn->isPrimaryKey() && $this->table->getClassname() != $this->getForeignTable($relatedColumn)->getClassname())
- {
- // we have the related table
- $tables[] = array(
- 'middleTable' => $table,
- 'relatedTable' => $this->getForeignTable($relatedColumn),
- 'column' => $column,
- 'relatedColumn' => $relatedColumn,
- );
-
- break 2;
- }
- }
+ $columns = $relations[$foreignTableName]->getLocalColumns();
+ $relatedColumns = $foreignRelation->getLocalColumns();
+
+ $tables[] = array(
+ 'middleTable' => $foreignRelation->getLocalTable(),
+ 'relatedTable' => $foreignTable,
+ 'column' => reset($columns),
+ 'relatedColumn' => reset($relatedColumns),
+ );
+ continue 2;
}
}
}
-
return $tables;
}
@@ -66,38 +66,48 @@ public function getTableMap()
public function getManyToManyTables()
{
$tables = array();
+ $foreignTables = array();
+ $relations = array();
- // go through all tables to find m2m relationships
- foreach ($this->dbMap->getTables() as $tableName => $table)
+ // go through all relations
+ foreach ($this->getTableMap()->getRelations() as $relation)
{
- // load this table's relations and related tables
- $table->getRelations();
+ //we have a many to many Relation
+ if (RelationMap::MANY_TO_MANY === $relation->getType())
+ {
+ $foreignTables[$relation->getLocalTable()->getClassname()] = $relation->getLocalTable();
+ }
+ else if (RelationMap::ONE_TO_MANY === $relation->getType())
+ {
+ $relations[$relation->getLocalTable()->getClassname()] = $relation;
+ }
+ }
- foreach ($table->getColumns() as $column)
+ // find middleTable for Many to Many relation
+ foreach ($foreignTables as $tableName => $foreignTable)
+ {
+ foreach ($foreignTable->getRelations() as $foreignRelation)
{
- if ($column->isForeignKey() && $column->isPrimaryKey() && $this->getTableMap()->getClassname() == $this->dbMap->getTable($column->getRelatedTableName())->getClassname())
+ $foreignTableName = $foreignRelation->getLocalTable()->getClassname();
+
+ // Test if the foreign table has a common relation with our table
+ // TODO: test if is CrossRef
+ if (RelationMap::ONE_TO_MANY === $foreignRelation->getType()
+ && array_key_exists($foreignTableName, $relations))
{
- // we have a m2m relationship
- // find the other primary key
- foreach ($table->getColumns() as $relatedColumn)
- {
- if ($relatedColumn->isForeignKey() && $relatedColumn->isPrimaryKey() && $this->getTableMap()->getClassname() != $this->dbMap->getTable($relatedColumn->getRelatedTableName())->getClassname())
- {
- // we have the related table
- $tables[] = array(
- 'middleTable' => $table,
- 'relatedTable' => $this->dbMap->getTable($relatedColumn->getRelatedTableName()),
- 'column' => $column,
- 'relatedColumn' => $relatedColumn,
- );
-
- break 2;
- }
- }
+ $columns = $relations[$foreignTableName]->getLocalColumns();
+ $relatedColumns = $foreignRelation->getLocalColumns();
+
+ $tables[] = array(
+ 'middleTable' => $foreignRelation->getLocalTable(),
+ 'relatedTable' => $foreignTable,
+ 'column' => reset($columns),
+ 'relatedColumn' => reset($relatedColumns),
+ );
+ continue 2;
}
}
}
-
return $tables;
}
@@ -46,7 +46,7 @@
<column name="hobbies" type="array" required="false" />
</table>
- <table name="author_article">
+ <table name="author_article" isCrossref="true">
<behavior name="symfony">
<parameter name="form" value="false"/>
<parameter name="filter" value="false"/>
@@ -150,4 +150,21 @@
<column name="id" type="integer" required="true" primaryKey="true" autoincrement="true" />
<column name="enum_values" type="enum" valueSet="one, two, three space" />
</table>
+
+ <!-- model and data for testing many to many -->
+ <table name="seller">
+ <column name="id" type="integer" required="true" primaryKey="true" autoincrement="true" />
+ <column name="name" type="varchar" size="255" />
+ </table>
+ <table name="sale">
+ <column name="seller_id" type="integer" primaryKey="true" />
+ <column name="book_id" type="integer" primaryKey="true" />
+ <column name="number" type="integer" />
+ <foreign-key foreignTable="seller">
+ <reference local="seller_id" foreign="id" />
+ </foreign-key>
+ <foreign-key foreignTable="book">
+ <reference local="book_id" foreign="id" />
+ </foreign-key>
+ </table>
</database>
@@ -291,3 +291,20 @@
checkElement('select option[selected="selected"]', 'three space')->
end()
;
+
+//Checks that many-to-many relations are generated correctly
+$form = new SellerForm();
+try {
+ $form->getWidget('sale_list');
+ $b->test()->fail('The seller form shoud not has sale_list field because it is not a many to many relation');
+} catch (InvalidArgumentException $e) {
+ $b->test()->pass('The seller form shoud not has sale_list field because it is not a many to many relation');
+}
+
+$form = new BookForm();
+try {
+ $form->getWidget('sale_list');
+ $b->test()->fail('The book form shoud not has sale_list field because it is not a many to many relation');
+} catch (InvalidArgumentException $e) {
+ $b->test()->pass('The book form shoud not has sale_list field because it is not a many to many relation');
+}

0 comments on commit cc91e66

Please sign in to comment.