diff --git a/src/Faker/ORM/Doctrine/EntityPopulator.php b/src/Faker/ORM/Doctrine/EntityPopulator.php index 0949df36..5422f814 100644 --- a/src/Faker/ORM/Doctrine/EntityPopulator.php +++ b/src/Faker/ORM/Doctrine/EntityPopulator.php @@ -17,6 +17,10 @@ class EntityPopulator * @var array */ protected $columnFormatters = array(); + /** + * @var array + */ + protected $modifiers = array(); /** * Class constructor. @@ -51,6 +55,21 @@ class EntityPopulator $this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters); } + public function setModifiers(array $modifiers) + { + $this->modifiers = $modifiers; + } + + public function getModifiers() + { + return $this->modifiers; + } + + public function mergeModifiersWith(array $modifiers) + { + $this->modifiers = array_merge($this->modifiers, $modifiers); + } + public function guessColumnFormatters(\Faker\Generator $generator) { $formatters = array(); @@ -78,7 +97,27 @@ class EntityPopulator } $relatedClass = $this->class->getAssociationTargetClass($assocName); - $formatters[$assocName] = function($inserted) use ($relatedClass) { return isset($inserted[$relatedClass]) ? $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)] : null; }; + + $unique = false; + $mappings = $this->class->getAssociationMappings(); + foreach ($mappings as $mapping) { + if ($mapping['targetEntity'] == $relatedClass) { + if ($mapping['type'] == ClassMetadata::ONE_TO_ONE) { + $unique = true; + break; + } + } + } + + $index = 0; + $formatters[$assocName] = function($inserted) use ($relatedClass, &$index, $unique) { + if ($unique && isset($inserted[$relatedClass])) { + return $inserted[$relatedClass][$index++]; + } else if (isset($inserted[$relatedClass])) { + return $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)]; + } + return null; + }; } return $formatters; @@ -87,18 +126,18 @@ class EntityPopulator /** * Insert one new record using the Entity class. */ - public function execute($manager, $insertedEntities) + public function execute($manager, $insertedEntities, $generateId = false) { $obj = $this->class->newInstance(); - foreach ($this->columnFormatters as $field => $format) { - if (null !== $format) { - $value = is_callable($format) ? $format($insertedEntities, $obj) : $format; - if (is_callable(array($obj, $field))) { - $obj->$field($value); - } else { - $this->class->reflFields[$field]->setValue($obj, $value); - } + $this->fillColumns($obj, $insertedEntities); + $this->callMethods($obj, $insertedEntities); + + if ($generateId) { + $idsName = $this->class->getIdentifier(); + foreach ($idsName as $idName) { + $id = $this->generateId($obj, $idName, $manager); + $this->class->reflFields[$idName]->setValue($obj, $id); } } @@ -107,4 +146,42 @@ class EntityPopulator return $obj; } + private function fillColumns($obj, $insertedEntities) + { + foreach ($this->columnFormatters as $field => $format) { + if (null !== $format) { + $value = is_callable($format) ? $format($insertedEntities, $obj) : $format; + $this->class->reflFields[$field]->setValue($obj, $value); + } + } + } + + private function callMethods($obj, $insertedEntities) + { + foreach ($this->getModifiers() as $method => $formats) { + $args = array(); + foreach ($formats as $format) { + $args[] = is_callable($format) ? $format($insertedEntities, $obj) : $format; + } + call_user_func_array(array($obj, $method), $args); + } + } + + private function generateId($obj, $column, $manager) + { + /* @var $repository \Doctrine\ORM\EntityRepository */ + $repository = $manager->getRepository(get_class($obj)); + $result = $repository->createQueryBuilder('e') + ->select(sprintf('e.%s', $column)) + ->getQuery() + ->getResult(); + $ids = array_map('current', $result); + + $id = null; + do { + $id = rand(); + } while(in_array($id, $ids)); + + return $id; + } } diff --git a/src/Faker/ORM/Doctrine/Populator.php b/src/Faker/ORM/Doctrine/Populator.php index 070b8aaa..59e50041 100644 --- a/src/Faker/ORM/Doctrine/Populator.php +++ b/src/Faker/ORM/Doctrine/Populator.php @@ -14,6 +14,7 @@ class Populator protected $manager; protected $entities = array(); protected $quantities = array(); + protected $generateId = array(); public function __construct(\Faker\Generator $generator, ObjectManager $manager = null) { @@ -27,7 +28,7 @@ class Populator * @param mixed $entity A Doctrine classname, or a \Faker\ORM\Doctrine\EntityPopulator instance * @param int $number The number of entities to populate */ - public function addEntity($entity, $number, $customColumnFormatters = array()) + public function addEntity($entity, $number, $customColumnFormatters = array(), $customModifiers = array(), $generateId = false) { if (!$entity instanceof \Faker\ORM\Doctrine\EntityPopulator) { $entity = new \Faker\ORM\Doctrine\EntityPopulator($this->manager->getClassMetadata($entity)); @@ -36,6 +37,9 @@ class Populator if ($customColumnFormatters) { $entity->mergeColumnFormattersWith($customColumnFormatters); } + $entity->mergeModifiersWith($customModifiers); + $this->generateId[$entity->getClass()] = $generateId; + $class = $entity->getClass(); $this->entities[$class] = $entity; $this->quantities[$class] = $number; @@ -59,8 +63,9 @@ class Populator $insertedEntities = array(); foreach ($this->quantities as $class => $number) { + $generateId = $this->generateId[$class]; for ($i=0; $i < $number; $i++) { - $insertedEntities[$class][]= $this->entities[$class]->execute($entityManager, $insertedEntities); + $insertedEntities[$class][]= $this->entities[$class]->execute($entityManager, $insertedEntities, $generateId); } $entityManager->flush(); }