Skip to content

Commit

Permalink
[DataFixtures] Fixed N-N relations
Browse files Browse the repository at this point in the history
  • Loading branch information
willdurand committed May 6, 2012
1 parent 35dbf79 commit 2e7bb13
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 157 deletions.
6 changes: 4 additions & 2 deletions DataFixtures/AbstractDataHandler.php
Expand Up @@ -11,7 +11,6 @@
namespace Propel\PropelBundle\DataFixtures;

use \Propel;

use Symfony\Component\Finder\Finder;

/**
Expand Down Expand Up @@ -65,7 +64,10 @@ protected function loadMapBuilders($connectionName = null)

if (0 === count($this->dbMap->getTables())) {
$finder = new Finder();
$files = $finder->files()->name('*TableMap.php')->in($this->getRootDir() . '/../')->exclude('Tests');
$files = $finder->files()->name('*TableMap.php')
->in($this->getRootDir() . '/../')
->exclude('PropelBundle')
->exclude('Tests');

foreach ($files as $file) {
$class = $this->guessFullClassName($file->getRelativePath(), basename($file, '.php'));
Expand Down
41 changes: 21 additions & 20 deletions DataFixtures/Loader/AbstractDataLoader.php
Expand Up @@ -10,15 +10,14 @@

namespace Propel\PropelBundle\DataFixtures\Loader;

use \Propel;

use \BasePeer;
use \BaseObject;
use \ColumnMap;
use \Propel;
use \PropelException;

use Propel\PropelBundle\DataFixtures\AbstractDataHandler;
use Propel\PropelBundle\Util\PropelInflector;

use Symfony\Component\Finder\Finder;

/**
Expand Down Expand Up @@ -156,17 +155,18 @@ protected function loadDataFromArray($data = null)
}

foreach ($data as $name => $value) {
try {
if (is_array($value) && 's' === substr($name, -1)) {
if (is_array($value) && 's' === substr($name, -1)) {
try {
// many to many relationship
$this->loadManyToMany($obj, substr($name, 0, -1), $value);

continue;
}
} catch (\PropelException $e) {
// Check whether this is actually an array stored in the object.
if ('Cannot fetch TableMap for undefined table: '.substr($name, 0, -1) === $e->getMessage()) {
if ('ARRAY' !== $tableMap->getColumn($name)->getType()) {
throw $e;
} catch (PropelException $e) {
// Check whether this is actually an array stored in the object.
if ('Cannot fetch TableMap for undefined table: '.substr($name, 0, -1) === $e->getMessage()) {
if ('ARRAY' !== $tableMap->getColumn($name)->getType()) {
throw $e;
}
}
}
}
Expand Down Expand Up @@ -206,8 +206,7 @@ protected function loadDataFromArray($data = null)

if (false !== $pos = array_search($name, $column_names)) {
$obj->setByPosition($pos, $value);
}
elseif (is_callable(array($obj, $method = 'set'.ucfirst(PropelInflector::camelize($name))))) {
} elseif (is_callable(array($obj, $method = 'set'.ucfirst(PropelInflector::camelize($name))))) {
$obj->$method($value);
} else {
throw new \InvalidArgumentException(sprintf('Column "%s" does not exist for class "%s".', $name, $class));
Expand All @@ -234,22 +233,24 @@ protected function loadDataFromArray($data = null)
protected function loadManyToMany($obj, $middleTableName, $values)
{
$middleTable = $this->dbMap->getTable($middleTableName);
$middleClass = $middleTable->getPhpName();
$middleClass = $middleTable->getClassname();
$tableName = constant(constant(get_class($obj).'::PEER').'::TABLE_NAME');

foreach ($middleTable->getColumns() as $column) {
if ($column->isForeignKey() && constant(constant(get_class($obj).'::PEER').'::TABLE_NAME') != $column->getRelatedTableName()) {
$relatedClass = $this->dbMap->getTable($column->getRelatedTableName())->getPhpName();
break;
if ($column->isForeignKey()) {
if ($tableName !== $column->getRelatedTableName()) {
$relatedClass = $this->dbMap->getTable($column->getRelatedTableName())->getClassname();
$relatedSetter = 'set' . $column->getRelation()->getName();
} else {
$setter = 'set' . $column->getRelation()->getName();
}
}
}

if (!isset($relatedClass)) {
throw new \InvalidArgumentException(sprintf('Unable to find the many-to-many relationship for object "%s".', get_class($obj)));
}

$setter = 'set'.get_class($obj);
$relatedSetter = 'set'.$relatedClass;

foreach ($values as $value) {
if (!isset($this->object_references[$relatedClass.'_'.$value])) {
throw new \InvalidArgumentException(
Expand Down
15 changes: 13 additions & 2 deletions Resources/doc/README.markdown
Expand Up @@ -262,15 +262,26 @@ A valid _XML fixtures file_ is:
A valid _YAML fixtures file_ is:

``` yaml
\Awesome\Object:
Awesome\Object:
o1:
Title: My title
MyFoo: bar

\Awesome\Related:
Awesome\Related:
r1:
ObjectId: o1
Description: Hello world !

Awesome\Tag:
t1:
name: Foo
t2:
name: Baz

Awesome\Post:
p1:
title: A Post with tags (N-N relation)
tags: [ t1, t2 ]
```

You can load all fixtures files from a given _bundle_:
Expand Down
41 changes: 29 additions & 12 deletions Tests/DataFixtures/Loader/YamlDataLoaderTest.php
Expand Up @@ -49,42 +49,52 @@ public function testYamlLoadManyToMany()
{
$schema = <<<XML
<database name="default" package="vendor.bundles.Propel.PropelBundle.Tests.Fixtures.DataFixtures.Loader" namespace="Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader" defaultIdMethod="native">
<table name="book" phpName="YamlManyToManyBook">
<table name="table_book" phpName="YamlManyToManyBook">
<column name="id" type="integer" primaryKey="true" />
<column name="name" type="varchar" size="255" />
</table>
<table name="author" phpName="YamlManyToManyAuthor">
<table name="table_author" phpName="YamlManyToManyAuthor">
<column name="id" type="integer" primaryKey="true" />
<column name="name" type="varchar" size="255" />
</table>
<table name="book_author" phpName="YamlManyToManyBookAuthor">
<table name="table_book_author" phpName="YamlManyToManyBookAuthor" isCrossRef="true">
<column name="book_id" type="integer" required="true" primaryKey="true" />
<column name="author_id" type="integer" required="true" primaryKey="true" />
<foreign-key foreignTable="book" phpName="Book" onDelete="CASCADE" onUpdate="CASCADE">
<foreign-key foreignTable="table_book" phpName="Book" onDelete="CASCADE" onUpdate="CASCADE">
<reference local="book_id" foreign="id" />
</foreign-key>
<foreign-key foreignTable="author" phpName="Author" onDelete="CASCADE" onUpdate="CASCADE">
<foreign-key foreignTable="table_author" phpName="Author" onDelete="CASCADE" onUpdate="CASCADE">
<reference local="author_id" foreign="id" />
</foreign-key>
</table>
</database>
XML;

$fixtures = <<<YAML
Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthor:
Author_1:
name: 'A famous one'
Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBook:
Book_1:
id: 1
name: 'An important one'
Book_2:
id: 2
name: 'Les misérables'
Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthor:
Author_1:
id: 1
name: 'A famous one'
Author_2:
id: 2
name: 'Victor Hugo'
table_book_authors: [ Book_2 ]
Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookAuthor:
BookAuthor_1:
book_id: Book_1
author_id: Author_1
YAML;

$filename = $this->getTempFile($fixtures);
Expand All @@ -97,16 +107,23 @@ public function testYamlLoadManyToMany()
$loader->load(array($filename), 'default');

$books = \Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookPeer::doSelect(new \Criteria(), $con);
$this->assertCount(1, $books);
$this->assertCount(2, $books);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBook', $books[0]);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBook', $books[1]);

$authors = \Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthorPeer::doSelect(new \Criteria(), $con);
$this->assertCount(1, $authors);
$this->assertCount(2, $authors);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthor', $authors[0]);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyAuthor', $authors[1]);

$bookAuthors = \Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookAuthorPeer::doSelect(new \Criteria(), $con);
$this->assertCount(1, $bookAuthors);
$this->assertCount(2, $bookAuthors);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookAuthor', $bookAuthors[0]);
$this->assertInstanceOf('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\YamlManyToManyBookAuthor', $bookAuthors[1]);

$this->assertEquals('Victor Hugo', $authors[1]->getName());
$this->assertTrue($authors[1]->getBooks()->contains($books[1]));
$this->assertEquals('Les misérables', $authors[1]->getBooks()->get(0)->getName());
}

public function testLoadSelfReferencing()
Expand Down
4 changes: 1 addition & 3 deletions Tests/DataFixtures/TestCase.php
Expand Up @@ -56,9 +56,7 @@ protected function setUp()

$builder = new \PropelQuickBuilder();
$builder->setSchema($schema);
if (!class_exists('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\Book')) {
$builder->setClassTargets(array('peer', 'object', 'query', 'peerstub', 'objectstub', 'querystub'));
} else {
if (class_exists('Propel\PropelBundle\Tests\Fixtures\DataFixtures\Loader\Book')) {
$builder->setClassTargets(array());
}

Expand Down
58 changes: 0 additions & 58 deletions Tests/Fixtures/DataFixtures/Loader/map/BookAuthorTableMap.php

This file was deleted.

59 changes: 0 additions & 59 deletions Tests/Fixtures/DataFixtures/Loader/map/BookTableMap.php

This file was deleted.

2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -13,7 +13,7 @@
"propel/propel1": "1.6.*"
},
"require-dev": {
"sensio/framework-extra-bundle": "*"
"sensio/framework-extra-bundle": "dev-master"
},
"autoload": {
"psr-0": { "Propel\\PropelBundle": "" }
Expand Down

0 comments on commit 2e7bb13

Please sign in to comment.