Skip to content

Commit

Permalink
Merge pull request #90 from jaugustin/refactor-get-many-to-many
Browse files Browse the repository at this point in the history
Propel Generator: for getManyToManyTables use real ManyToMany, fixes #88,
  • Loading branch information
willdurand committed Mar 11, 2012
2 parents b3c15ff + d84cb02 commit cc91e66
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 47 deletions.
57 changes: 35 additions & 22 deletions lib/generator/sfPropelFormGenerator.class.php
Expand Up @@ -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;
}

Expand Down
58 changes: 34 additions & 24 deletions lib/generator/sfPropelGenerator.class.php
Expand Up @@ -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;
}

Expand Down
19 changes: 18 additions & 1 deletion test/functional/fixtures/config/schema.xml
Expand Up @@ -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"/>
Expand Down Expand Up @@ -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>
17 changes: 17 additions & 0 deletions test/functional/formTest.php
Expand Up @@ -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.