Skip to content

Commit

Permalink
Merge pull request #37 from h4cc/feature/fixes
Browse files Browse the repository at this point in the history
Made references of sets and files global for commands.
  • Loading branch information
h4cc committed Oct 28, 2014
2 parents 2fb8ad6 + f375c46 commit 8228ce5
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 17 deletions.
8 changes: 7 additions & 1 deletion Command/LoadFilesCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
$schemaTool->createSchema();
}

// Store all loaded references in this array, so they can be used by other FixtureSets.
$references = array();

foreach ($files as $file) {
$output->write("Loading file '$file' ... ");

Expand All @@ -83,7 +86,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
$set->setLocale($input->getOption('locale'));
$set->setSeed($input->getOption('seed'));

$entities = $manager->load($set);
$entities = $manager->load($set, $references);

// Only reusing loaded entities. Internal references are ignored because of intended private state.
$references = array_merge($references, $entities);

$output->writeln("loaded " . count($entities) . " entities ... done.");
}
Expand Down
21 changes: 18 additions & 3 deletions Command/LoadSetsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ protected function configure()
->setName('h4cc_alice_fixtures:load:sets')
->setDescription('Load fixture sets using alice and faker.')
->addArgument('sets', InputArgument::IS_ARRAY, 'List of path to fixture sets to import.')
->addOption('manager', 'm', InputOption::VALUE_OPTIONAL, 'The manager name to used.', 'default');
->addOption('manager', 'm', InputOption::VALUE_OPTIONAL, 'The manager name to used.', 'default')
->addOption('drop', 'd', InputOption::VALUE_NONE, 'Drop and create Schema before loading.');
}

protected function execute(InputInterface $input, OutputInterface $output)
Expand All @@ -55,16 +56,27 @@ protected function execute(InputInterface $input, OutputInterface $output)
}

$managerServiceId = 'h4cc_alice_fixtures.manager';
$schemaToolServiceId = 'h4cc_alice_fixtures.orm.schema_tool';

if ('default' !== $input->getOption('manager')) {
$managerServiceId = sprintf('h4cc_alice_fixtures.%s_manager', $input->getOption('manager'));
$managerServiceId = sprintf('h4cc_alice_fixtures.%s_manager', $input->getOption('manager'));
$schemaToolServiceId = sprintf('h4cc_alice_fixtures.orm.%s_schema_tool', $input->getOption('manager'));
}

/**
* @var $manager \h4cc\AliceFixturesBundle\Fixtures\FixtureManager
*/
$manager = $this->getContainer()->get($managerServiceId);

if ($input->getOption('drop')) {
$schemaTool = $this->getContainer()->get($schemaToolServiceId);
$schemaTool->dropSchema();
$schemaTool->createSchema();
}

// Store all loaded references in this array, so they can be used by other FixtureSets.
$references = array();

foreach ($sets as $file) {
$output->write("Loading file '$file' ... ");

Expand All @@ -75,7 +87,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
throw new \InvalidArgumentException("File '$file' does not return a FixtureSetInterface.");
}

$entities = $manager->load($set);
$entities = $manager->load($set, $references);

// Only reusing loaded entities. Internal references are ignored because of intended private state.
$references = array_merge($references, $entities);

$output->writeln("loaded " . count($entities) . " entities ... done.");
}
Expand Down
7 changes: 2 additions & 5 deletions Fixtures/FixtureManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,14 @@ public function createFixtureSet()
/**
* {@inheritDoc}
*/
public function load(FixtureSet $set)
public function load(FixtureSet $set, array $initialReferences = array())
{
$loaders = $this->createNeededLoaders($set);

// Objects are the loaded entities without "local".
$objects = array();
// References contain, _all_ objects loaded. Needed only for loading.
$references = array();
$references = $initialReferences;

// Load each file
foreach ($set->getFiles() as $file) {
Expand All @@ -159,9 +159,6 @@ public function load(FixtureSet $set)
$this->logDebug("Persisted " . count($objects) . " loaded objects.");
}

// Detach entities
$this->getORM()->detach($objects);

return $objects;
}

Expand Down
5 changes: 4 additions & 1 deletion Fixtures/FixtureManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,13 @@ public function createFixtureSet();
* Loads objects/entities from given FixtureSet.
* The FixtureSet Object will decide, if drop or persist will be done as well as all other parameters.
*
* The initial references array can be used to provide already loaded entities so they can be referenced.
*
* @param FixtureSet $set
* @param array $initialReferences
* @return mixed
*/
public function load(FixtureSet $set);
public function load(FixtureSet $set, array $initialReferences = array());

/**
* Persists all given entities.
Expand Down
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ This means _all_ tables managed by Doctrine will be dropped and recreated. A dat
## Installation

Simply require the bundle by its name with composer:

```bash
$ php composer.phar require h4cc/alice-fixtures-bundle
```
Follow the 'dev-master' branch for latest dev version. But i recommend to use more stable version tags if available.


After that, add the Bundle to your Kernel, most likely in the "dev" or "test" environment.

```php
<?php
// app/AppKernel.php
Expand Down Expand Up @@ -108,6 +110,7 @@ h4cc_alice_fixtures:
```
Check out this command for a always up-to-date configuration reference:
```
$ php app/console config:dump-reference h4cc_alice_fixtures
```
Expand Down Expand Up @@ -146,6 +149,7 @@ A more advanced way of loading fixtures is using "FixtureSets".
Look at it like a fixture configuration object for multiple fixture files and options.

Example:

```php
$manager = $this->getContainer()->get('h4cc_alice_fixtures.manager');

Expand Down Expand Up @@ -177,23 +181,31 @@ h4cc_alice_fixtures
h4cc_alice_fixtures:load:sets Load fixture sets using alice and faker.
```

By default, all fixture files or sets will share their references. This way a Bundle can reference the fixtures from another bundles.

Example for loading single files using all available options:

```bash
$ php app/console h4cc_alice_fixtures:load:files --manager=default --type=yaml --seed=42 --local=de_DE --no-persist --drop src/Acme/DemoBundle/Fixtures/Users.yml src/Acme/DemoBundle/Fixtures/Articles.yml
```

Example command for loading the given FixtureSet:

```bash
$ php app/console h4cc_alice_fixtures:load:sets src/Acme/DemoBundle/Fixtures/UsersAndArticlesSet.php
```

When your FixtureSets are stored at the default path 'DataFixtures/Alice/' and are named like 'ExampleSet.php', they can be found automaticaly. Like the fixtures in Doctrine Datafixtures do.
When your FixtureSets are stored at the default path 'DataFixtures/Alice/' and are named ending in ...'Set.php', they can be found automaticaly. Like the fixtures in Doctrine Datafixtures do.
To load the default fixture sets, simply execute this command:

```bash
$ php app/console h4cc_alice_fixtures:load:sets
```

Preconfigured FixtureSet:
The order in which the bundles are loaded is defined by the order in which they are defined in `AppKernel`.

Example for a Preconfigured FixtureSet:

```php
<?php

Expand All @@ -212,6 +224,13 @@ return $set;
```
Such a file has to return a Object with the FixtureSetInterface Interface.

### FixtureSets from different Bundles

When using multiple bundles like `MyCommonBundle` and `MyUserBundle`, there are a few things to do and know:

* The order in which `h4cc_alice_fixtures:load:sets` will load FixtureSets will be the same order as in `AppKernel::registerBundles().
* All FixtureSets will use a global state of references. This way the `MyUserBundle` can use entities from `MyCommonBundle`.
* A circular-reference between FixtureSets is not possible, because only already loaded entities can be referenced.

## Demo Application

Expand All @@ -226,6 +245,7 @@ If needed, the fixtures can also be loaded in a PHPUnit test.
Accessing the needed container in a Symfony2 environment is described here: http://symfony.com/doc/current/book/testing.html#accessing-the-container

Example:

```php
// Ensuring the same fixtures for each testcase.
public function setUp()
Expand All @@ -250,6 +270,7 @@ These methods can be used in the fixture files for own testdata or even calculat
To register a provider, create a service and tag it.

Example:

```yaml
services:
your.faker.provider:
Expand All @@ -264,6 +285,7 @@ A alice processor can be used to manipulate a object _before_ and _after_ persis
To register a own processor, create a service and tag it.
Example:
```yaml
services:
your.alice.processor:
Expand Down
4 changes: 2 additions & 2 deletions Tests/Command/LoadFilesCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public function setUp()

public function testLoad()
{
$this->managerMock->expects($this->once())->method('load');
$this->managerMock->expects($this->once())->method('load')->willReturn(array('abc' => 42));

$tester = new CommandTester($this->command);

Expand All @@ -80,7 +80,7 @@ public function testLoad()

public function testLoadWithoutDefaultManager()
{
$this->managerMock->expects($this->once())->method('load');
$this->managerMock->expects($this->once())->method('load')->willReturn(array('abc' => 42));

$tester = new CommandTester($this->command);

Expand Down
7 changes: 4 additions & 3 deletions Tests/Command/LoadSetsCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public function setUp()

public function testLoad()
{
$this->managerMock->expects($this->once())->method('load');
$this->managerMock->expects($this->once())->method('load')->willReturn(array('abc' => 42));

$tester = new CommandTester($this->command);

Expand All @@ -78,7 +78,7 @@ public function testLoad()

public function testLoadWithoutDefaultManager()
{
$this->managerMock->expects($this->once())->method('load');
$this->managerMock->expects($this->once())->method('load')->willReturn(array('abc' => 42));

$tester = new CommandTester($this->command);

Expand Down Expand Up @@ -120,14 +120,15 @@ public function testLoadErrorNoSets()
public function testLoadWithDefaultLoadedSet()
{
$this->bundleMock->expects($this->any())->method('getPath')->will($this->returnValue(__DIR__.'/SampleBundle'));
$this->managerMock->expects($this->once())->method('load')->willReturn(array('abc' => 42));

$tester = new CommandTester($this->command);

$tester->execute(
array('command' => $this->command->getName())
);

$this->assertEquals("Loading file '".__DIR__.'/SampleBundle'."/DataFixtures/Alice/FooSet.php' ... loaded 0 entities ... done.\n", $tester->getDisplay());
$this->assertEquals("Loading file '".__DIR__.'/SampleBundle'."/DataFixtures/Alice/FooSet.php' ... loaded 1 entities ... done.\n", $tester->getDisplay());
}

/**
Expand Down

0 comments on commit 8228ce5

Please sign in to comment.