From ebcc92bf4850077978f6cee129efb723c3a8d757 Mon Sep 17 00:00:00 2001 From: Francois Zaninotto Date: Sat, 14 Apr 2012 23:54:05 +0200 Subject: [PATCH] Add the ability to execute arbitrary modifier function on an entity. Propel Only for now: support for tree structures (nested_set behavior). --- readme.md | 9 +++ src/Faker/ORM/Propel/EntityPopulator.php | 73 +++++++++++++++++++++++- src/Faker/ORM/Propel/Populator.php | 6 +- 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index ee4bdadb..94f7dc1a 100644 --- a/readme.md +++ b/readme.md @@ -233,6 +233,15 @@ print_r($insertedPKs); In the previous example, the `Book` and `Author` models share a relationship. Since `Author` entities are populated first, Faker is smart enough to relate the populated `Book` entities to one of the populated `Author` entities. +Lastly, if you want to execute an arbitrary function on an entity before insertion, use the fourth argument of the `addEntity()` method: + +```php +addEntity('Book', 5, array(), array( + function($book) { $book->publish(); }, +)); +``` + ## Seeding the Generator You may want to get always the same generated data - for instance when using Faker for unit testing purposes. The generator offers a `seed()` method, which seeds the random number generator. Calling the same script twice with the same seed produces the same results. diff --git a/src/Faker/ORM/Propel/EntityPopulator.php b/src/Faker/ORM/Propel/EntityPopulator.php index 8300e29b..2ebd753f 100644 --- a/src/Faker/ORM/Propel/EntityPopulator.php +++ b/src/Faker/ORM/Propel/EntityPopulator.php @@ -9,6 +9,7 @@ class EntityPopulator { protected $class; protected $columnFormatters = array(); + protected $modifiers = array(); /** * Class constructor. @@ -49,9 +50,13 @@ class EntityPopulator $nameGuesser = new \Faker\Guesser\Name($generator); $columnTypeGuesser = new \Faker\ORM\Propel\ColumnTypeGuesser($generator); foreach ($tableMap->getColumns() as $columnMap) { + // skip behavior columns, handled by modifiers + if ($this->isColumnBehavior($columnMap)) { + continue; + } if ($columnMap->isForeignKey()) { $relatedClass = $columnMap->getRelation()->getForeignTable()->getClassname(); - $formatters[$columnMap->getPhpName()] = function($inserted) use($relatedClass) { return isset($inserted[$relatedClass]) ? $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)] : null; }; + $formatters[$columnMap->getPhpName()] = function($inserted) use ($relatedClass) { return isset($inserted[$relatedClass]) ? $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)] : null; }; continue; } if ($columnMap->isPrimaryKey()) { @@ -68,6 +73,67 @@ class EntityPopulator } return $formatters; } + + protected function isColumnBehavior($columnMap) + { + foreach ($columnMap->getTable()->getBehaviors() as $name => $params) { + $columnName = strtolower($columnMap->getName()); + switch ($name) { + case 'nested_set': + $columnNames = array($params['left_column'], $params['right_column'], $params['level_column']); + if (in_array($columnName, $columnNames)) { + return true; + } + break; + case 'timestampable': + $columnNames = array($params['create_column'], $params['update_column']); + if (in_array($columnName, $columnNames)) { + return true; + } + break; + } + } + return false; + } + + public function setModifiers($modifiers) + { + $this->modifiers = $modifiers; + } + + public function getModifiers() + { + return $this->modifiers; + } + + public function mergeModifiersWith($modifiers) + { + $this->modifiers = array_merge($this->modifiers, $modifiers); + } + + public function guessModifiers(\Faker\Generator $generator) + { + $modifiers = array(); + $class = $this->class; + $peerClass = $class::PEER; + $tableMap = $peerClass::getTableMap(); + foreach ($tableMap->getBehaviors() as $name => $params) { + switch ($name) { + case 'nested_set': + $modifiers['nested_set'] = function($obj, $inserted) use ($class, $generator) { + if (isset($inserted[$class])) { + $queryClass = $class . 'Query'; + $parent = $queryClass::create()->findPk($generator->randomElement($inserted[$class])); + $obj->insertAsLastChildOf($parent); + } else { + $obj->makeRoot(); + } + }; + break; + } + } + return $modifiers; + } /** * Insert one new record using the Entity class. @@ -75,11 +141,14 @@ class EntityPopulator public function execute($con, $insertedEntities) { $obj = new $this->class(); - foreach ($this->columnFormatters as $column => $format) { + foreach ($this->getColumnFormatters() as $column => $format) { if (null !== $column) { $obj->setByName($column, is_callable($format) ? $format($insertedEntities, $obj) : $format); } } + foreach ($this->getModifiers() as $modifier) { + $modifier($obj, $insertedEntities); + } $obj->save($con); return $obj->getPrimaryKey(); diff --git a/src/Faker/ORM/Propel/Populator.php b/src/Faker/ORM/Propel/Populator.php index 7b2e033c..9d3c7766 100644 --- a/src/Faker/ORM/Propel/Populator.php +++ b/src/Faker/ORM/Propel/Populator.php @@ -23,7 +23,7 @@ class Populator * @param mixed $entity A Propel ActiveRecord classname, or a \Faker\ORM\Propel\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()) { if (!$entity instanceof \Faker\ORM\Propel\EntityPopulator) { $entity = new \Faker\ORM\Propel\EntityPopulator($entity); @@ -32,6 +32,10 @@ class Populator if ($customColumnFormatters) { $entity->mergeColumnFormattersWith($customColumnFormatters); } + $entity->setModifiers($entity->guessModifiers($this->generator)); + if ($customModifiers) { + $entity->mergeModifiersWith($customModifiers); + } $class = $entity->getClass(); $this->entities[$class] = $entity; $this->quantities[$class] = $number;