mirror of
https://github.com/fzaninotto/Faker.git
synced 2025-04-20 23:41:50 +02:00
Merge pull request #1957 from pimjansen/feature/removed-orm-integrations
Removed all the ORM/ODM integrations from the core
This commit is contained in:
commit
abb76321d4
@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
### Removed
|
||||
|
||||
- Removed legacy autoloader [\#1911](https://github.com/fzaninotto/Faker/pull/1911) ([pimjansen](https://github.com/pimjansen))
|
||||
- Removed ORM and ODM integrations [\#1957](https://github.com/fzaninotto/Faker/pull/1957) ([pimjansen](https://github.com/pimjansen))
|
||||
|
||||
## 2019-11-10, v1.9.0
|
||||
|
||||
|
66
readme.md
66
readme.md
@ -37,7 +37,6 @@ Faker requires PHP >= 5.3.3.
|
||||
- [Html Lorem](#fakerproviderhtmllorem)
|
||||
- [Modifiers](#modifiers)
|
||||
- [Localization](#localization)
|
||||
- [Populating Entities Using an ORM or an ODM](#populating-entities-using-an-orm-or-an-odm)
|
||||
- [Seeding the Generator](#seeding-the-generator)
|
||||
- [Faker Internals: Understanding Providers](#faker-internals-understanding-providers)
|
||||
- [Real Life Usage](#real-life-usage)
|
||||
@ -414,71 +413,6 @@ for ($i = 0; $i < 10; $i++) {
|
||||
|
||||
You can check available Faker locales in the source code, [under the `Provider` directory](https://github.com/fzaninotto/Faker/tree/master/src/Faker/Provider). The localization of Faker is an ongoing process, for which we need your help. Don't hesitate to create localized providers to your own locale and submit a PR!
|
||||
|
||||
## Populating Entities Using an ORM or an ODM
|
||||
|
||||
Faker provides adapters for Object-Relational and Object-Document Mappers (currently, [Propel](http://www.propelorm.org), [Doctrine2](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/), [CakePHP](http://cakephp.org), [Spot2](https://github.com/vlucas/spot2), [Mandango](https://github.com/mandango/mandango) and [Eloquent](https://laravel.com/docs/master/eloquent) are supported). These adapters ease the population of databases through the Entity classes provided by an ORM library (or the population of document stores using Document classes provided by an ODM library).
|
||||
|
||||
To populate entities, create a new populator class (using a generator instance as parameter), then list the class and number of all the entities that must be generated. To launch the actual data population, call the `execute()` method.
|
||||
|
||||
Note that some of the `populators` could require additional parameters. As example the `doctrine` populator has an option to specify
|
||||
its batchSize on how often it will flush the UnitOfWork to the database.
|
||||
|
||||
Here is an example showing how to populate 5 `Author` and 10 `Book` objects:
|
||||
|
||||
```php
|
||||
<?php
|
||||
$generator = \Faker\Factory::create();
|
||||
$populator = new \Faker\ORM\Propel\Populator($generator);
|
||||
$populator->addEntity('Author', 5);
|
||||
$populator->addEntity('Book', 10);
|
||||
$insertedPKs = $populator->execute();
|
||||
```
|
||||
|
||||
The populator uses name and column type guessers to populate each column with relevant data. For instance, Faker populates a column named `first_name` using the `firstName` formatter, and a column with a `TIMESTAMP` type using the `dateTime` formatter. The resulting entities are therefore coherent. If Faker misinterprets a column name, you can still specify a custom closure to be used for populating a particular column, using the third argument to `addEntity()`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
$populator->addEntity('Book', 5, array(
|
||||
'ISBN' => function() use ($generator) { return $generator->ean13(); }
|
||||
));
|
||||
```
|
||||
|
||||
In this example, Faker will guess a formatter for all columns except `ISBN`, for which the given anonymous function will be used.
|
||||
|
||||
**Tip**: To ignore some columns, specify `null` for the column names in the third argument of `addEntity()`. This is usually necessary for columns added by a behavior:
|
||||
|
||||
```php
|
||||
<?php
|
||||
$populator->addEntity('Book', 5, array(
|
||||
'CreatedAt' => null,
|
||||
'UpdatedAt' => null,
|
||||
));
|
||||
```
|
||||
|
||||
Of course, Faker does not populate autoincremented primary keys. In addition, `Faker\ORM\Propel\Populator::execute()` returns the list of inserted PKs, indexed by class:
|
||||
|
||||
```php
|
||||
<?php
|
||||
print_r($insertedPKs);
|
||||
// array(
|
||||
// 'Author' => (34, 35, 36, 37, 38),
|
||||
// 'Book' => (456, 457, 458, 459, 470, 471, 472, 473, 474, 475)
|
||||
// )
|
||||
```
|
||||
|
||||
**Note:** Due to the fact that `Faker` returns all the primary keys inserted, the memory consumption will go up drastically when you do batch inserts due to the big list of data.
|
||||
|
||||
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
|
||||
<?php
|
||||
$populator->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.
|
||||
|
@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\CakePHP;
|
||||
|
||||
class ColumnTypeGuesser
|
||||
{
|
||||
protected $generator;
|
||||
|
||||
public function __construct(\Faker\Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Closure|null
|
||||
*/
|
||||
public function guessFormat($column, $table)
|
||||
{
|
||||
$generator = $this->generator;
|
||||
$schema = $table->schema();
|
||||
|
||||
switch ($schema->columnType($column)) {
|
||||
case 'boolean':
|
||||
return function () use ($generator) {
|
||||
return $generator->boolean;
|
||||
};
|
||||
case 'integer':
|
||||
return function () {
|
||||
return mt_rand(0, intval('2147483647'));
|
||||
};
|
||||
case 'biginteger':
|
||||
return function () {
|
||||
return mt_rand(0, intval('9223372036854775807'));
|
||||
};
|
||||
case 'decimal':
|
||||
case 'float':
|
||||
return function () use ($generator) {
|
||||
return $generator->randomFloat();
|
||||
};
|
||||
case 'uuid':
|
||||
return function () use ($generator) {
|
||||
return $generator->uuid();
|
||||
};
|
||||
case 'string':
|
||||
if (method_exists($schema, 'getColumn')) {
|
||||
$columnData = $schema->getColumn($column);
|
||||
} else {
|
||||
$columnData = $schema->column($column);
|
||||
}
|
||||
$length = $columnData['length'];
|
||||
return function () use ($generator, $length) {
|
||||
return $generator->text($length);
|
||||
};
|
||||
case 'text':
|
||||
return function () use ($generator) {
|
||||
return $generator->text();
|
||||
};
|
||||
case 'date':
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
case 'time':
|
||||
return function () use ($generator) {
|
||||
return $generator->datetime();
|
||||
};
|
||||
|
||||
case 'binary':
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\CakePHP;
|
||||
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class EntityPopulator
|
||||
{
|
||||
protected $class;
|
||||
protected $connectionName;
|
||||
protected $columnFormatters = [];
|
||||
protected $modifiers = [];
|
||||
|
||||
public function __construct($class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->{$name};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->{$name} = $value;
|
||||
}
|
||||
|
||||
public function mergeColumnFormattersWith($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters);
|
||||
}
|
||||
|
||||
public function mergeModifiersWith($modifiers)
|
||||
{
|
||||
$this->modifiers = array_merge($this->modifiers, $modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function guessColumnFormatters($populator)
|
||||
{
|
||||
$formatters = [];
|
||||
$class = $this->class;
|
||||
$table = $this->getTable($class);
|
||||
$schema = $table->schema();
|
||||
$pk = $schema->primaryKey();
|
||||
$guessers = $populator->getGuessers() + ['ColumnTypeGuesser' => new ColumnTypeGuesser($populator->getGenerator())];
|
||||
$isForeignKey = function ($column) use ($table) {
|
||||
foreach ($table->associations()->type('BelongsTo') as $assoc) {
|
||||
if ($column == $assoc->foreignKey()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
foreach ($schema->columns() as $column) {
|
||||
if ($column == $pk[0] || $isForeignKey($column)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($guessers as $guesser) {
|
||||
if ($formatter = $guesser->guessFormat($column, $table)) {
|
||||
$formatters[$column] = $formatter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $formatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function guessModifiers()
|
||||
{
|
||||
$modifiers = [];
|
||||
$table = $this->getTable($this->class);
|
||||
|
||||
$belongsTo = $table->associations()->type('BelongsTo');
|
||||
foreach ($belongsTo as $assoc) {
|
||||
$modifiers['belongsTo' . $assoc->name()] = function ($data, $insertedEntities) use ($assoc) {
|
||||
$table = $assoc->target();
|
||||
$foreignModel = $table->alias();
|
||||
|
||||
$foreignKeys = [];
|
||||
if (!empty($insertedEntities[$foreignModel])) {
|
||||
$foreignKeys = $insertedEntities[$foreignModel];
|
||||
} else {
|
||||
$foreignKeys = $table->find('all')
|
||||
->select(['id'])
|
||||
->map(function ($row) {
|
||||
return $row->id;
|
||||
})
|
||||
->toArray();
|
||||
}
|
||||
|
||||
if (empty($foreignKeys)) {
|
||||
throw new \Exception(sprintf('%s belongsTo %s, which seems empty at this point.', $this->getTable($this->class)->table(), $assoc->table()));
|
||||
}
|
||||
|
||||
$foreignKey = $foreignKeys[array_rand($foreignKeys)];
|
||||
$data[$assoc->foreignKey()] = $foreignKey;
|
||||
return $data;
|
||||
};
|
||||
}
|
||||
|
||||
// TODO check if TreeBehavior attached to modify lft/rgt cols
|
||||
|
||||
return $modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
*/
|
||||
public function execute($class, $insertedEntities, $options = [])
|
||||
{
|
||||
$table = $this->getTable($class);
|
||||
$entity = $table->newEntity();
|
||||
|
||||
foreach ($this->columnFormatters as $column => $format) {
|
||||
if (!is_null($format)) {
|
||||
$entity->{$column} = is_callable($format) ? $format($insertedEntities, $table) : $format;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->modifiers as $modifier) {
|
||||
$entity = $modifier($entity, $insertedEntities);
|
||||
}
|
||||
|
||||
if (!$entity = $table->save($entity, $options)) {
|
||||
throw new \RuntimeException("Failed saving $class record");
|
||||
}
|
||||
|
||||
$pk = $table->primaryKey();
|
||||
if (is_string($pk)) {
|
||||
return $entity->{$pk};
|
||||
}
|
||||
|
||||
return $entity->{$pk[0]};
|
||||
}
|
||||
|
||||
public function setConnection($name)
|
||||
{
|
||||
$this->connectionName = $name;
|
||||
}
|
||||
|
||||
protected function getTable($class)
|
||||
{
|
||||
$options = [];
|
||||
if (!empty($this->connectionName)) {
|
||||
$options['connection'] = $this->connectionName;
|
||||
}
|
||||
return TableRegistry::get($class, $options);
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\CakePHP;
|
||||
|
||||
class Populator
|
||||
{
|
||||
|
||||
protected $generator;
|
||||
protected $entities = [];
|
||||
protected $quantities = [];
|
||||
protected $guessers = [];
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
*/
|
||||
public function __construct(\Faker\Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Faker\Generator
|
||||
*/
|
||||
public function getGenerator()
|
||||
{
|
||||
return $this->generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getGuessers()
|
||||
{
|
||||
return $this->guessers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function removeGuesser($name)
|
||||
{
|
||||
if ($this->guessers[$name]) {
|
||||
unset($this->guessers[$name]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addGuesser($class)
|
||||
{
|
||||
if (!is_object($class)) {
|
||||
$class = new $class($this->generator);
|
||||
}
|
||||
|
||||
if (!method_exists($class, 'guessFormat')) {
|
||||
throw new \Exception('Missing required custom guesser method: ' . get_class($class) . '::guessFormat()');
|
||||
}
|
||||
|
||||
$this->guessers[get_class($class)] = $class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $customColumnFormatters
|
||||
* @param array $customModifiers
|
||||
* @return $this
|
||||
*/
|
||||
public function addEntity($entity, $number, $customColumnFormatters = [], $customModifiers = [])
|
||||
{
|
||||
if (!$entity instanceof EntityPopulator) {
|
||||
$entity = new EntityPopulator($entity);
|
||||
}
|
||||
|
||||
$entity->columnFormatters = $entity->guessColumnFormatters($this);
|
||||
if ($customColumnFormatters) {
|
||||
$entity->mergeColumnFormattersWith($customColumnFormatters);
|
||||
}
|
||||
|
||||
$entity->modifiers = $entity->guessModifiers($this);
|
||||
if ($customModifiers) {
|
||||
$entity->mergeModifiersWith($customModifiers);
|
||||
}
|
||||
|
||||
$class = $entity->class;
|
||||
$this->entities[$class] = $entity;
|
||||
$this->quantities[$class] = $number;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
public function execute($options = [])
|
||||
{
|
||||
$insertedEntities = [];
|
||||
|
||||
foreach ($this->quantities as $class => $number) {
|
||||
for ($i = 0; $i < $number; $i++) {
|
||||
$insertedEntities[$class][] = $this->entities[$class]->execute($class, $insertedEntities, $options);
|
||||
}
|
||||
}
|
||||
|
||||
return $insertedEntities;
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Doctrine;
|
||||
|
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
|
||||
|
||||
class ColumnTypeGuesser
|
||||
{
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
*/
|
||||
public function __construct(\Faker\Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassMetadata $class
|
||||
* @return \Closure|null
|
||||
*/
|
||||
public function guessFormat($fieldName, ClassMetadata $class)
|
||||
{
|
||||
$generator = $this->generator;
|
||||
$type = $class->getTypeOfField($fieldName);
|
||||
switch ($type) {
|
||||
case 'boolean':
|
||||
return function () use ($generator) {
|
||||
return $generator->boolean;
|
||||
};
|
||||
case 'decimal':
|
||||
$size = isset($class->fieldMappings[$fieldName]['precision']) ? $class->fieldMappings[$fieldName]['precision'] : 2;
|
||||
|
||||
return function () use ($generator, $size) {
|
||||
return $generator->randomNumber($size + 2) / 100;
|
||||
};
|
||||
case 'smallint':
|
||||
return function () {
|
||||
return mt_rand(0, 65535);
|
||||
};
|
||||
case 'integer':
|
||||
return function () {
|
||||
return mt_rand(0, intval('2147483647'));
|
||||
};
|
||||
case 'bigint':
|
||||
return function () {
|
||||
return mt_rand(0, intval('18446744073709551615'));
|
||||
};
|
||||
case 'float':
|
||||
return function () {
|
||||
return mt_rand(0, intval('4294967295'))/mt_rand(1, intval('4294967295'));
|
||||
};
|
||||
case 'string':
|
||||
$size = isset($class->fieldMappings[$fieldName]['length']) ? $class->fieldMappings[$fieldName]['length'] : 255;
|
||||
|
||||
return function () use ($generator, $size) {
|
||||
return $generator->text($size);
|
||||
};
|
||||
case 'text':
|
||||
return function () use ($generator) {
|
||||
return $generator->text;
|
||||
};
|
||||
case 'datetime':
|
||||
case 'date':
|
||||
case 'time':
|
||||
return function () use ($generator) {
|
||||
return $generator->datetime;
|
||||
};
|
||||
case 'datetime_immutable':
|
||||
case 'date_immutable':
|
||||
case 'time_immutable':
|
||||
return function () use ($generator) {
|
||||
return \DateTimeImmutable::createFromMutable($generator->datetime);
|
||||
};
|
||||
default:
|
||||
// no smart way to guess what the user expects here
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,251 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Doctrine;
|
||||
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
|
||||
|
||||
/**
|
||||
* Service class for populating a table through a Doctrine Entity class.
|
||||
*/
|
||||
class EntityPopulator
|
||||
{
|
||||
/**
|
||||
* @var ClassMetadata
|
||||
*/
|
||||
protected $class;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $columnFormatters = array();
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $modifiers = array();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param ClassMetadata $class
|
||||
*/
|
||||
public function __construct(ClassMetadata $class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClass()
|
||||
{
|
||||
return $this->class->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columnFormatters
|
||||
*/
|
||||
public function setColumnFormatters($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = $columnFormatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnFormatters()
|
||||
{
|
||||
return $this->columnFormatters;
|
||||
}
|
||||
|
||||
public function mergeColumnFormattersWith($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $modifiers
|
||||
*/
|
||||
public function setModifiers(array $modifiers)
|
||||
{
|
||||
$this->modifiers = $modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getModifiers()
|
||||
{
|
||||
return $this->modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $modifiers
|
||||
*/
|
||||
public function mergeModifiersWith(array $modifiers)
|
||||
{
|
||||
$this->modifiers = array_merge($this->modifiers, $modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
* @return array
|
||||
*/
|
||||
public function guessColumnFormatters(\Faker\Generator $generator)
|
||||
{
|
||||
$formatters = array();
|
||||
$nameGuesser = new \Faker\Guesser\Name($generator);
|
||||
$columnTypeGuesser = new ColumnTypeGuesser($generator);
|
||||
foreach ($this->class->getFieldNames() as $fieldName) {
|
||||
if ($this->class->isIdentifier($fieldName) || !$this->class->hasField($fieldName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$size = isset($this->class->fieldMappings[$fieldName]['length']) ? $this->class->fieldMappings[$fieldName]['length'] : null;
|
||||
if ($formatter = $nameGuesser->guessFormat($fieldName, $size)) {
|
||||
$formatters[$fieldName] = $formatter;
|
||||
continue;
|
||||
}
|
||||
if ($formatter = $columnTypeGuesser->guessFormat($fieldName, $this->class)) {
|
||||
$formatters[$fieldName] = $formatter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->class->getAssociationNames() as $assocName) {
|
||||
if ($this->class->isCollectionValuedAssociation($assocName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$relatedClass = $this->class->getAssociationTargetClass($assocName);
|
||||
|
||||
$unique = $optional = false;
|
||||
if ($this->class instanceof \Doctrine\ORM\Mapping\ClassMetadata) {
|
||||
$mappings = $this->class->getAssociationMappings();
|
||||
foreach ($mappings as $mapping) {
|
||||
if ($mapping['targetEntity'] == $relatedClass) {
|
||||
if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_ONE) {
|
||||
$unique = true;
|
||||
$optional = isset($mapping['joinColumns'][0]['nullable']) ? $mapping['joinColumns'][0]['nullable'] : false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ($this->class instanceof \Doctrine\ODM\MongoDB\Mapping\ClassMetadata) {
|
||||
$mappings = $this->class->associationMappings;
|
||||
foreach ($mappings as $mapping) {
|
||||
if ($mapping['targetDocument'] == $relatedClass) {
|
||||
if ($mapping['type'] == \Doctrine\ODM\MongoDB\Mapping\ClassMetadata::ONE && $mapping['association'] == \Doctrine\ODM\MongoDB\Mapping\ClassMetadata::REFERENCE_ONE) {
|
||||
$unique = true;
|
||||
$optional = isset($mapping['nullable']) ? $mapping['nullable'] : false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$index = 0;
|
||||
$formatters[$assocName] = function ($inserted) use ($relatedClass, &$index, $unique, $optional) {
|
||||
|
||||
if (isset($inserted[$relatedClass])) {
|
||||
if ($unique) {
|
||||
$related = null;
|
||||
if (isset($inserted[$relatedClass][$index]) || !$optional) {
|
||||
$related = $inserted[$relatedClass][$index];
|
||||
}
|
||||
|
||||
$index++;
|
||||
|
||||
return $related;
|
||||
}
|
||||
|
||||
return $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)];
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
return $formatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert one new record using the Entity class.
|
||||
* @param ObjectManager $manager
|
||||
* @param bool $generateId
|
||||
* @return EntityPopulator
|
||||
*/
|
||||
public function execute(ObjectManager $manager, $insertedEntities, $generateId = false)
|
||||
{
|
||||
$obj = $this->class->newInstance();
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
$manager->persist($obj);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
private function fillColumns($obj, $insertedEntities)
|
||||
{
|
||||
foreach ($this->columnFormatters as $field => $format) {
|
||||
if (null !== $format) {
|
||||
// Add some extended debugging information to any errors thrown by the formatter
|
||||
try {
|
||||
$value = is_callable($format) ? $format($insertedEntities, $obj) : $format;
|
||||
} catch (\InvalidArgumentException $ex) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
"Failed to generate a value for %s::%s: %s",
|
||||
get_class($obj),
|
||||
$field,
|
||||
$ex->getMessage()
|
||||
));
|
||||
}
|
||||
// Try a standard setter if it's available, otherwise fall back on reflection
|
||||
$setter = sprintf("set%s", ucfirst($field));
|
||||
if (is_callable(array($obj, $setter))) {
|
||||
$obj->$setter($value);
|
||||
} else {
|
||||
$this->class->reflFields[$field]->setValue($obj, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function callMethods($obj, $insertedEntities)
|
||||
{
|
||||
foreach ($this->getModifiers() as $modifier) {
|
||||
$modifier($obj, $insertedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return int|null
|
||||
*/
|
||||
private function generateId($obj, $column, ObjectManager $manager)
|
||||
{
|
||||
/* @var $repository \Doctrine\Common\Persistence\ObjectRepository */
|
||||
$repository = $manager->getRepository(get_class($obj));
|
||||
$result = $repository->createQueryBuilder('e')
|
||||
->select(sprintf('e.%s', $column))
|
||||
->getQuery()
|
||||
->execute();
|
||||
$ids = array_map('current', $result->toArray());
|
||||
|
||||
$id = null;
|
||||
do {
|
||||
$id = mt_rand();
|
||||
} while (in_array($id, $ids));
|
||||
|
||||
return $id;
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Doctrine;
|
||||
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Faker\Generator;
|
||||
|
||||
/**
|
||||
* Service class for populating a database using the Doctrine ORM or ODM.
|
||||
* A Populator can populate several tables using ActiveRecord classes.
|
||||
*/
|
||||
class Populator
|
||||
{
|
||||
/** @var int */
|
||||
protected $batchSize;
|
||||
|
||||
/** @var Generator */
|
||||
protected $generator;
|
||||
|
||||
/** @var ObjectManager|null */
|
||||
protected $manager;
|
||||
|
||||
/** @var array */
|
||||
protected $entities = array();
|
||||
|
||||
/** @var array */
|
||||
protected $quantities = array();
|
||||
|
||||
/** @var array */
|
||||
protected $generateId = array();
|
||||
|
||||
/**
|
||||
* Populator constructor.
|
||||
* @param Generator $generator
|
||||
* @param ObjectManager|null $manager
|
||||
* @param int $batchSize
|
||||
*/
|
||||
public function __construct(Generator $generator, ObjectManager $manager = null, $batchSize = 1000)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
$this->manager = $manager;
|
||||
$this->batchSize = $batchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an order for the generation of $number records for $entity.
|
||||
*
|
||||
* @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(), $customModifiers = array(), $generateId = false)
|
||||
{
|
||||
if (!$entity instanceof \Faker\ORM\Doctrine\EntityPopulator) {
|
||||
if (null === $this->manager) {
|
||||
throw new \InvalidArgumentException("No entity manager passed to Doctrine Populator.");
|
||||
}
|
||||
$entity = new \Faker\ORM\Doctrine\EntityPopulator($this->manager->getClassMetadata($entity));
|
||||
}
|
||||
$entity->setColumnFormatters($entity->guessColumnFormatters($this->generator));
|
||||
if ($customColumnFormatters) {
|
||||
$entity->mergeColumnFormattersWith($customColumnFormatters);
|
||||
}
|
||||
$entity->mergeModifiersWith($customModifiers);
|
||||
$this->generateId[$entity->getClass()] = $generateId;
|
||||
|
||||
$class = $entity->getClass();
|
||||
$this->entities[$class] = $entity;
|
||||
$this->quantities[$class] = $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the database using all the Entity classes previously added.
|
||||
*
|
||||
* Please note that large amounts of data will result in more memory usage since the the Populator will return
|
||||
* all newly created primary keys after executing.
|
||||
*
|
||||
* @param null|EntityManager $entityManager A Doctrine connection object
|
||||
*
|
||||
* @return array A list of the inserted PKs
|
||||
*/
|
||||
public function execute($entityManager = null)
|
||||
{
|
||||
if (null === $entityManager) {
|
||||
$entityManager = $this->manager;
|
||||
}
|
||||
if (null === $entityManager) {
|
||||
throw new \InvalidArgumentException("No entity manager passed to Doctrine 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,
|
||||
$generateId
|
||||
);
|
||||
if (count($insertedEntities) % $this->batchSize === 0) {
|
||||
$entityManager->flush();
|
||||
$entityManager->clear($class);
|
||||
}
|
||||
}
|
||||
$entityManager->flush();
|
||||
$entityManager->clear($class);
|
||||
}
|
||||
|
||||
return $insertedEntities;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Mandango;
|
||||
|
||||
class ColumnTypeGuesser
|
||||
{
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
*/
|
||||
public function __construct(\Faker\Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Closure|null
|
||||
*/
|
||||
public function guessFormat($field)
|
||||
{
|
||||
$generator = $this->generator;
|
||||
switch ($field['type']) {
|
||||
case 'boolean':
|
||||
return function () use ($generator) {
|
||||
return $generator->boolean;
|
||||
};
|
||||
case 'integer':
|
||||
return function () {
|
||||
return mt_rand(0, intval('4294967295'));
|
||||
};
|
||||
case 'float':
|
||||
return function () {
|
||||
return mt_rand(0, intval('4294967295'))/mt_rand(1, intval('4294967295'));
|
||||
};
|
||||
case 'string':
|
||||
return function () use ($generator) {
|
||||
return $generator->text(255);
|
||||
};
|
||||
case 'date':
|
||||
return function () use ($generator) {
|
||||
return $generator->datetime;
|
||||
};
|
||||
default:
|
||||
// no smart way to guess what the user expects here
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Mandango;
|
||||
|
||||
use Mandango\Mandango;
|
||||
use Faker\Provider\Base;
|
||||
|
||||
/**
|
||||
* Service class for populating a table through a Mandango ActiveRecord class.
|
||||
*/
|
||||
class EntityPopulator
|
||||
{
|
||||
protected $class;
|
||||
protected $columnFormatters = array();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $class A Mandango ActiveRecord classname
|
||||
*/
|
||||
public function __construct($class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClass()
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
public function setColumnFormatters($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = $columnFormatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnFormatters()
|
||||
{
|
||||
return $this->columnFormatters;
|
||||
}
|
||||
|
||||
public function mergeColumnFormattersWith($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
* @param Mandango $mandango
|
||||
* @return array
|
||||
*/
|
||||
public function guessColumnFormatters(\Faker\Generator $generator, Mandango $mandango)
|
||||
{
|
||||
$formatters = array();
|
||||
$nameGuesser = new \Faker\Guesser\Name($generator);
|
||||
$columnTypeGuesser = new \Faker\ORM\Mandango\ColumnTypeGuesser($generator);
|
||||
|
||||
$metadata = $mandango->getMetadata($this->class);
|
||||
|
||||
// fields
|
||||
foreach ($metadata['fields'] as $fieldName => $field) {
|
||||
if ($formatter = $nameGuesser->guessFormat($fieldName)) {
|
||||
$formatters[$fieldName] = $formatter;
|
||||
continue;
|
||||
}
|
||||
if ($formatter = $columnTypeGuesser->guessFormat($field)) {
|
||||
$formatters[$fieldName] = $formatter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// references
|
||||
foreach (array_merge($metadata['referencesOne'], $metadata['referencesMany']) as $referenceName => $reference) {
|
||||
if (!isset($reference['class'])) {
|
||||
continue;
|
||||
}
|
||||
$referenceClass = $reference['class'];
|
||||
|
||||
$formatters[$referenceName] = function ($insertedEntities) use ($referenceClass) {
|
||||
if (isset($insertedEntities[$referenceClass])) {
|
||||
return Base::randomElement($insertedEntities[$referenceClass]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return $formatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert one new record using the Entity class.
|
||||
* @param Mandango $mandango
|
||||
*/
|
||||
public function execute(Mandango $mandango, $insertedEntities)
|
||||
{
|
||||
$metadata = $mandango->getMetadata($this->class);
|
||||
|
||||
$obj = $mandango->create($this->class);
|
||||
foreach ($this->columnFormatters as $column => $format) {
|
||||
if (null !== $format) {
|
||||
$value = is_callable($format) ? $format($insertedEntities, $obj) : $format;
|
||||
|
||||
if (isset($metadata['fields'][$column]) ||
|
||||
isset($metadata['referencesOne'][$column])) {
|
||||
$obj->set($column, $value);
|
||||
}
|
||||
|
||||
if (isset($metadata['referencesMany'][$column])) {
|
||||
$adder = 'add'.ucfirst($column);
|
||||
$obj->$adder($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
$mandango->persist($obj);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Mandango;
|
||||
|
||||
use Mandango\Mandango;
|
||||
|
||||
/**
|
||||
* Service class for populating a database using Mandango.
|
||||
* A Populator can populate several tables using ActiveRecord classes.
|
||||
*/
|
||||
class Populator
|
||||
{
|
||||
protected $generator;
|
||||
protected $mandango;
|
||||
protected $entities = array();
|
||||
protected $quantities = array();
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
* @param Mandango $mandango
|
||||
*/
|
||||
public function __construct(\Faker\Generator $generator, Mandango $mandango)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
$this->mandango = $mandango;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an order for the generation of $number records for $entity.
|
||||
*
|
||||
* @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())
|
||||
{
|
||||
if (!$entity instanceof \Faker\ORM\Mandango\EntityPopulator) {
|
||||
$entity = new \Faker\ORM\Mandango\EntityPopulator($entity);
|
||||
}
|
||||
$entity->setColumnFormatters($entity->guessColumnFormatters($this->generator, $this->mandango));
|
||||
if ($customColumnFormatters) {
|
||||
$entity->mergeColumnFormattersWith($customColumnFormatters);
|
||||
}
|
||||
$class = $entity->getClass();
|
||||
$this->entities[$class] = $entity;
|
||||
$this->quantities[$class] = $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the database using all the Entity classes previously added.
|
||||
*
|
||||
* @return array A list of the inserted entities.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$insertedEntities = array();
|
||||
foreach ($this->quantities as $class => $number) {
|
||||
for ($i=0; $i < $number; $i++) {
|
||||
$insertedEntities[$class][]= $this->entities[$class]->execute($this->mandango, $insertedEntities);
|
||||
}
|
||||
}
|
||||
$this->mandango->flush();
|
||||
|
||||
return $insertedEntities;
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Propel;
|
||||
|
||||
use \PropelColumnTypes;
|
||||
use \ColumnMap;
|
||||
|
||||
class ColumnTypeGuesser
|
||||
{
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
*/
|
||||
public function __construct(\Faker\Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ColumnMap $column
|
||||
* @return \Closure|null
|
||||
*/
|
||||
public function guessFormat(ColumnMap $column)
|
||||
{
|
||||
$generator = $this->generator;
|
||||
if ($column->isTemporal()) {
|
||||
if ($column->isEpochTemporal()) {
|
||||
return function () use ($generator) {
|
||||
return $generator->dateTime;
|
||||
};
|
||||
}
|
||||
|
||||
return function () use ($generator) {
|
||||
return $generator->dateTimeAD;
|
||||
};
|
||||
}
|
||||
$type = $column->getType();
|
||||
switch ($type) {
|
||||
case PropelColumnTypes::BOOLEAN:
|
||||
case PropelColumnTypes::BOOLEAN_EMU:
|
||||
return function () use ($generator) {
|
||||
return $generator->boolean;
|
||||
};
|
||||
case PropelColumnTypes::NUMERIC:
|
||||
case PropelColumnTypes::DECIMAL:
|
||||
$size = $column->getSize();
|
||||
|
||||
return function () use ($generator, $size) {
|
||||
return $generator->randomNumber($size + 2) / 100;
|
||||
};
|
||||
case PropelColumnTypes::TINYINT:
|
||||
return function () {
|
||||
return mt_rand(0, 127);
|
||||
};
|
||||
case PropelColumnTypes::SMALLINT:
|
||||
return function () {
|
||||
return mt_rand(0, 32767);
|
||||
};
|
||||
case PropelColumnTypes::INTEGER:
|
||||
return function () {
|
||||
return mt_rand(0, intval('2147483647'));
|
||||
};
|
||||
case PropelColumnTypes::BIGINT:
|
||||
return function () {
|
||||
return mt_rand(0, intval('9223372036854775807'));
|
||||
};
|
||||
case PropelColumnTypes::FLOAT:
|
||||
return function () {
|
||||
return mt_rand(0, intval('2147483647'))/mt_rand(1, intval('2147483647'));
|
||||
};
|
||||
case PropelColumnTypes::DOUBLE:
|
||||
case PropelColumnTypes::REAL:
|
||||
return function () {
|
||||
return mt_rand(0, intval('9223372036854775807'))/mt_rand(1, intval('9223372036854775807'));
|
||||
};
|
||||
case PropelColumnTypes::CHAR:
|
||||
case PropelColumnTypes::VARCHAR:
|
||||
case PropelColumnTypes::BINARY:
|
||||
case PropelColumnTypes::VARBINARY:
|
||||
$size = $column->getSize();
|
||||
|
||||
return function () use ($generator, $size) {
|
||||
return $generator->text($size);
|
||||
};
|
||||
case PropelColumnTypes::LONGVARCHAR:
|
||||
case PropelColumnTypes::LONGVARBINARY:
|
||||
case PropelColumnTypes::CLOB:
|
||||
case PropelColumnTypes::CLOB_EMU:
|
||||
case PropelColumnTypes::BLOB:
|
||||
return function () use ($generator) {
|
||||
return $generator->text;
|
||||
};
|
||||
case PropelColumnTypes::ENUM:
|
||||
$valueSet = $column->getValueSet();
|
||||
|
||||
return function () use ($generator, $valueSet) {
|
||||
return $generator->randomElement($valueSet);
|
||||
};
|
||||
case PropelColumnTypes::OBJECT:
|
||||
case PropelColumnTypes::PHP_ARRAY:
|
||||
default:
|
||||
// no smart way to guess what the user expects here
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,191 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Propel;
|
||||
|
||||
use \Faker\Provider\Base;
|
||||
use \ColumnMap;
|
||||
|
||||
/**
|
||||
* Service class for populating a table through a Propel ActiveRecord class.
|
||||
*/
|
||||
class EntityPopulator
|
||||
{
|
||||
protected $class;
|
||||
protected $columnFormatters = array();
|
||||
protected $modifiers = array();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $class A Propel ActiveRecord classname
|
||||
*/
|
||||
public function __construct($class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClass()
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
public function setColumnFormatters($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = $columnFormatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnFormatters()
|
||||
{
|
||||
return $this->columnFormatters;
|
||||
}
|
||||
|
||||
public function mergeColumnFormattersWith($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
* @return array
|
||||
*/
|
||||
public function guessColumnFormatters(\Faker\Generator $generator)
|
||||
{
|
||||
$formatters = array();
|
||||
$class = $this->class;
|
||||
$peerClass = $class::PEER;
|
||||
$tableMap = $peerClass::getTableMap();
|
||||
$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;
|
||||
};
|
||||
continue;
|
||||
}
|
||||
if ($columnMap->isPrimaryKey()) {
|
||||
continue;
|
||||
}
|
||||
if ($formatter = $nameGuesser->guessFormat($columnMap->getPhpName(), $columnMap->getSize())) {
|
||||
$formatters[$columnMap->getPhpName()] = $formatter;
|
||||
continue;
|
||||
}
|
||||
if ($formatter = $columnTypeGuesser->guessFormat($columnMap)) {
|
||||
$formatters[$columnMap->getPhpName()] = $formatter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $formatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ColumnMap $columnMap
|
||||
* @return bool
|
||||
*/
|
||||
protected function isColumnBehavior(ColumnMap $columnMap)
|
||||
{
|
||||
foreach ($columnMap->getTable()->getBehaviors() as $name => $params) {
|
||||
$columnName = Base::toLower($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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getModifiers()
|
||||
{
|
||||
return $this->modifiers;
|
||||
}
|
||||
|
||||
public function mergeModifiersWith($modifiers)
|
||||
{
|
||||
$this->modifiers = array_merge($this->modifiers, $modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
* @return array
|
||||
*/
|
||||
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;
|
||||
case 'sortable':
|
||||
$modifiers['sortable'] = function ($obj, $inserted) use ($class) {
|
||||
$maxRank = isset($inserted[$class]) ? count($inserted[$class]) : 0;
|
||||
$obj->insertAtRank(mt_rand(1, $maxRank + 1));
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert one new record using the Entity class.
|
||||
*/
|
||||
public function execute($con, $insertedEntities)
|
||||
{
|
||||
$obj = new $this->class();
|
||||
foreach ($this->getColumnFormatters() as $column => $format) {
|
||||
if (null !== $format) {
|
||||
$obj->setByName($column, is_callable($format) ? $format($insertedEntities, $obj) : $format);
|
||||
}
|
||||
}
|
||||
foreach ($this->getModifiers() as $modifier) {
|
||||
$modifier($obj, $insertedEntities);
|
||||
}
|
||||
$obj->save($con);
|
||||
|
||||
return $obj->getPrimaryKey();
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Propel;
|
||||
|
||||
/**
|
||||
* Service class for populating a database using the Propel ORM.
|
||||
* A Populator can populate several tables using ActiveRecord classes.
|
||||
*/
|
||||
class Populator
|
||||
{
|
||||
protected $generator;
|
||||
protected $entities = array();
|
||||
protected $quantities = array();
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
*/
|
||||
public function __construct(\Faker\Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an order for the generation of $number records for $entity.
|
||||
*
|
||||
* @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(), $customModifiers = array())
|
||||
{
|
||||
if (!$entity instanceof \Faker\ORM\Propel\EntityPopulator) {
|
||||
$entity = new \Faker\ORM\Propel\EntityPopulator($entity);
|
||||
}
|
||||
$entity->setColumnFormatters($entity->guessColumnFormatters($this->generator));
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the database using all the Entity classes previously added.
|
||||
*
|
||||
* @param PropelPDO $con A Propel connection object
|
||||
*
|
||||
* @return array A list of the inserted PKs
|
||||
*/
|
||||
public function execute($con = null)
|
||||
{
|
||||
if (null === $con) {
|
||||
$con = $this->getConnection();
|
||||
}
|
||||
$isInstancePoolingEnabled = \Propel::isInstancePoolingEnabled();
|
||||
\Propel::disableInstancePooling();
|
||||
$insertedEntities = array();
|
||||
$con->beginTransaction();
|
||||
foreach ($this->quantities as $class => $number) {
|
||||
for ($i=0; $i < $number; $i++) {
|
||||
$insertedEntities[$class][]= $this->entities[$class]->execute($con, $insertedEntities);
|
||||
}
|
||||
}
|
||||
$con->commit();
|
||||
if ($isInstancePoolingEnabled) {
|
||||
\Propel::enableInstancePooling();
|
||||
}
|
||||
|
||||
return $insertedEntities;
|
||||
}
|
||||
|
||||
protected function getConnection()
|
||||
{
|
||||
// use the first connection available
|
||||
$class = key($this->entities);
|
||||
|
||||
if (!$class) {
|
||||
throw new \RuntimeException('No class found from entities. Did you add entities to the Populator ?');
|
||||
}
|
||||
|
||||
$peer = $class::PEER;
|
||||
|
||||
return \Propel::getConnection($peer::DATABASE_NAME, \Propel::CONNECTION_WRITE);
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Propel2;
|
||||
|
||||
use \Propel\Generator\Model\PropelTypes;
|
||||
use \Propel\Runtime\Map\ColumnMap;
|
||||
|
||||
class ColumnTypeGuesser
|
||||
{
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
*/
|
||||
public function __construct(\Faker\Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ColumnMap $column
|
||||
* @return \Closure|null
|
||||
*/
|
||||
public function guessFormat(ColumnMap $column)
|
||||
{
|
||||
$generator = $this->generator;
|
||||
if ($column->isTemporal()) {
|
||||
if ($column->getType() == PropelTypes::BU_DATE || $column->getType() == PropelTypes::BU_TIMESTAMP) {
|
||||
return function () use ($generator) {
|
||||
return $generator->dateTime;
|
||||
};
|
||||
}
|
||||
|
||||
return function () use ($generator) {
|
||||
return $generator->dateTimeAD;
|
||||
};
|
||||
}
|
||||
$type = $column->getType();
|
||||
switch ($type) {
|
||||
case PropelTypes::BOOLEAN:
|
||||
case PropelTypes::BOOLEAN_EMU:
|
||||
return function () use ($generator) {
|
||||
return $generator->boolean;
|
||||
};
|
||||
case PropelTypes::NUMERIC:
|
||||
case PropelTypes::DECIMAL:
|
||||
$size = $column->getSize();
|
||||
|
||||
return function () use ($generator, $size) {
|
||||
return $generator->randomNumber($size + 2) / 100;
|
||||
};
|
||||
case PropelTypes::TINYINT:
|
||||
return function () {
|
||||
return mt_rand(0, 127);
|
||||
};
|
||||
case PropelTypes::SMALLINT:
|
||||
return function () {
|
||||
return mt_rand(0, 32767);
|
||||
};
|
||||
case PropelTypes::INTEGER:
|
||||
return function () {
|
||||
return mt_rand(0, intval('2147483647'));
|
||||
};
|
||||
case PropelTypes::BIGINT:
|
||||
return function () {
|
||||
return mt_rand(0, intval('9223372036854775807'));
|
||||
};
|
||||
case PropelTypes::FLOAT:
|
||||
return function () {
|
||||
return mt_rand(0, intval('2147483647'))/mt_rand(1, intval('2147483647'));
|
||||
};
|
||||
case PropelTypes::DOUBLE:
|
||||
case PropelTypes::REAL:
|
||||
return function () {
|
||||
return mt_rand(0, intval('9223372036854775807'))/mt_rand(1, intval('9223372036854775807'));
|
||||
};
|
||||
case PropelTypes::CHAR:
|
||||
case PropelTypes::VARCHAR:
|
||||
case PropelTypes::BINARY:
|
||||
case PropelTypes::VARBINARY:
|
||||
$size = $column->getSize();
|
||||
|
||||
return function () use ($generator, $size) {
|
||||
return $generator->text($size);
|
||||
};
|
||||
case PropelTypes::LONGVARCHAR:
|
||||
case PropelTypes::LONGVARBINARY:
|
||||
case PropelTypes::CLOB:
|
||||
case PropelTypes::CLOB_EMU:
|
||||
case PropelTypes::BLOB:
|
||||
return function () use ($generator) {
|
||||
return $generator->text;
|
||||
};
|
||||
case PropelTypes::ENUM:
|
||||
$valueSet = $column->getValueSet();
|
||||
|
||||
return function () use ($generator, $valueSet) {
|
||||
return $generator->randomElement($valueSet);
|
||||
};
|
||||
case PropelTypes::OBJECT:
|
||||
case PropelTypes::PHP_ARRAY:
|
||||
default:
|
||||
// no smart way to guess what the user expects here
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Propel2;
|
||||
|
||||
use \Faker\Provider\Base;
|
||||
use \Propel\Runtime\Map\ColumnMap;
|
||||
|
||||
/**
|
||||
* Service class for populating a table through a Propel ActiveRecord class.
|
||||
*/
|
||||
class EntityPopulator
|
||||
{
|
||||
protected $class;
|
||||
protected $columnFormatters = array();
|
||||
protected $modifiers = array();
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $class A Propel ActiveRecord classname
|
||||
*/
|
||||
public function __construct($class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClass()
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
public function setColumnFormatters($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = $columnFormatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnFormatters()
|
||||
{
|
||||
return $this->columnFormatters;
|
||||
}
|
||||
|
||||
public function mergeColumnFormattersWith($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
* @return array
|
||||
*/
|
||||
public function guessColumnFormatters(\Faker\Generator $generator)
|
||||
{
|
||||
$formatters = array();
|
||||
$class = $this->class;
|
||||
$peerClass = $class::TABLE_MAP;
|
||||
$tableMap = $peerClass::getTableMap();
|
||||
$nameGuesser = new \Faker\Guesser\Name($generator);
|
||||
$columnTypeGuesser = new \Faker\ORM\Propel2\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) {
|
||||
$relatedClass = trim($relatedClass, "\\");
|
||||
return isset($inserted[$relatedClass]) ? $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)] : null;
|
||||
};
|
||||
continue;
|
||||
}
|
||||
if ($columnMap->isPrimaryKey()) {
|
||||
continue;
|
||||
}
|
||||
if ($formatter = $nameGuesser->guessFormat($columnMap->getPhpName(), $columnMap->getSize())) {
|
||||
$formatters[$columnMap->getPhpName()] = $formatter;
|
||||
continue;
|
||||
}
|
||||
if ($formatter = $columnTypeGuesser->guessFormat($columnMap)) {
|
||||
$formatters[$columnMap->getPhpName()] = $formatter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $formatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ColumnMap $columnMap
|
||||
* @return bool
|
||||
*/
|
||||
protected function isColumnBehavior(ColumnMap $columnMap)
|
||||
{
|
||||
foreach ($columnMap->getTable()->getBehaviors() as $name => $params) {
|
||||
$columnName = Base::toLower($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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getModifiers()
|
||||
{
|
||||
return $this->modifiers;
|
||||
}
|
||||
|
||||
public function mergeModifiersWith($modifiers)
|
||||
{
|
||||
$this->modifiers = array_merge($this->modifiers, $modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
* @return array
|
||||
*/
|
||||
public function guessModifiers(\Faker\Generator $generator)
|
||||
{
|
||||
$modifiers = array();
|
||||
$class = $this->class;
|
||||
$peerClass = $class::TABLE_MAP;
|
||||
$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;
|
||||
case 'sortable':
|
||||
$modifiers['sortable'] = function ($obj, $inserted) use ($class) {
|
||||
$maxRank = isset($inserted[$class]) ? count($inserted[$class]) : 0;
|
||||
$obj->insertAtRank(mt_rand(1, $maxRank + 1));
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert one new record using the Entity class.
|
||||
*/
|
||||
public function execute($con, $insertedEntities)
|
||||
{
|
||||
$obj = new $this->class();
|
||||
foreach ($this->getColumnFormatters() as $column => $format) {
|
||||
if (null !== $format) {
|
||||
$obj->setByName($column, is_callable($format) ? $format($insertedEntities, $obj) : $format);
|
||||
}
|
||||
}
|
||||
foreach ($this->getModifiers() as $modifier) {
|
||||
$modifier($obj, $insertedEntities);
|
||||
}
|
||||
$obj->save($con);
|
||||
|
||||
return $obj->getPrimaryKey();
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Propel2;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
use Propel\Runtime\ServiceContainer\ServiceContainerInterface;
|
||||
|
||||
/**
|
||||
* Service class for populating a database using the Propel ORM.
|
||||
* A Populator can populate several tables using ActiveRecord classes.
|
||||
*/
|
||||
class Populator
|
||||
{
|
||||
protected $generator;
|
||||
protected $entities = array();
|
||||
protected $quantities = array();
|
||||
|
||||
/**
|
||||
* @param \Faker\Generator $generator
|
||||
*/
|
||||
public function __construct(\Faker\Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an order for the generation of $number records for $entity.
|
||||
*
|
||||
* @param mixed $entity A Propel ActiveRecord classname, or a \Faker\ORM\Propel2\EntityPopulator instance
|
||||
* @param int $number The number of entities to populate
|
||||
*/
|
||||
public function addEntity($entity, $number, $customColumnFormatters = array(), $customModifiers = array())
|
||||
{
|
||||
if (!$entity instanceof \Faker\ORM\Propel2\EntityPopulator) {
|
||||
$entity = new \Faker\ORM\Propel2\EntityPopulator($entity);
|
||||
}
|
||||
$entity->setColumnFormatters($entity->guessColumnFormatters($this->generator));
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the database using all the Entity classes previously added.
|
||||
*
|
||||
* @param PropelPDO $con A Propel connection object
|
||||
*
|
||||
* @return array A list of the inserted PKs
|
||||
*/
|
||||
public function execute($con = null)
|
||||
{
|
||||
if (null === $con) {
|
||||
$con = $this->getConnection();
|
||||
}
|
||||
$isInstancePoolingEnabled = Propel::isInstancePoolingEnabled();
|
||||
Propel::disableInstancePooling();
|
||||
$insertedEntities = array();
|
||||
$con->beginTransaction();
|
||||
foreach ($this->quantities as $class => $number) {
|
||||
for ($i=0; $i < $number; $i++) {
|
||||
$insertedEntities[$class][]= $this->entities[$class]->execute($con, $insertedEntities);
|
||||
}
|
||||
}
|
||||
$con->commit();
|
||||
if ($isInstancePoolingEnabled) {
|
||||
Propel::enableInstancePooling();
|
||||
}
|
||||
|
||||
return $insertedEntities;
|
||||
}
|
||||
|
||||
protected function getConnection()
|
||||
{
|
||||
// use the first connection available
|
||||
$class = key($this->entities);
|
||||
|
||||
if (!$class) {
|
||||
throw new \RuntimeException('No class found from entities. Did you add entities to the Populator ?');
|
||||
}
|
||||
|
||||
$peer = $class::TABLE_MAP;
|
||||
|
||||
return Propel::getConnection($peer::DATABASE_NAME, ServiceContainerInterface::CONNECTION_WRITE);
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Spot;
|
||||
|
||||
use Faker\Generator;
|
||||
|
||||
class ColumnTypeGuesser
|
||||
{
|
||||
protected $generator;
|
||||
|
||||
|
||||
/**
|
||||
* ColumnTypeGuesser constructor.
|
||||
* @param Generator $generator
|
||||
*/
|
||||
public function __construct(Generator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $field
|
||||
* @return \Closure|null
|
||||
*/
|
||||
public function guessFormat(array $field)
|
||||
{
|
||||
$generator = $this->generator;
|
||||
$type = $field['type'];
|
||||
switch ($type) {
|
||||
case 'boolean':
|
||||
return function () use ($generator) {
|
||||
return $generator->boolean;
|
||||
};
|
||||
case 'decimal':
|
||||
$size = isset($field['precision']) ? $field['precision'] : 2;
|
||||
|
||||
return function () use ($generator, $size) {
|
||||
return $generator->randomNumber($size + 2) / 100;
|
||||
};
|
||||
case 'smallint':
|
||||
return function () use ($generator) {
|
||||
return $generator->numberBetween(0, 65535);
|
||||
};
|
||||
case 'integer':
|
||||
return function () use ($generator) {
|
||||
return $generator->numberBetween(0, intval('2147483647'));
|
||||
};
|
||||
case 'bigint':
|
||||
return function () use ($generator) {
|
||||
return $generator->numberBetween(0, intval('18446744073709551615'));
|
||||
};
|
||||
case 'float':
|
||||
return function () use ($generator) {
|
||||
return $generator->randomFloat(null, 0, intval('4294967295'));
|
||||
};
|
||||
case 'string':
|
||||
$size = isset($field['length']) ? $field['length'] : 255;
|
||||
|
||||
return function () use ($generator, $size) {
|
||||
return $generator->text($size);
|
||||
};
|
||||
case 'text':
|
||||
return function () use ($generator) {
|
||||
return $generator->text;
|
||||
};
|
||||
case 'datetime':
|
||||
case 'date':
|
||||
case 'time':
|
||||
return function () use ($generator) {
|
||||
return $generator->datetime;
|
||||
};
|
||||
default:
|
||||
// no smart way to guess what the user expects here
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,219 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Faker\ORM\Spot;
|
||||
|
||||
use Faker\Generator;
|
||||
use Faker\Guesser\Name;
|
||||
use Spot\Locator;
|
||||
use Spot\Mapper;
|
||||
use Spot\Relation\BelongsTo;
|
||||
|
||||
/**
|
||||
* Service class for populating a table through a Spot Entity class.
|
||||
*/
|
||||
class EntityPopulator
|
||||
{
|
||||
/**
|
||||
* When fetching existing data - fetch only few first rows.
|
||||
*/
|
||||
const RELATED_FETCH_COUNT = 10;
|
||||
|
||||
/**
|
||||
* @var Mapper
|
||||
*/
|
||||
protected $mapper;
|
||||
|
||||
/**
|
||||
* @var Locator
|
||||
*/
|
||||
protected $locator;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $columnFormatters = array();
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $modifiers = array();
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $useExistingData = false;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param Mapper $mapper
|
||||
* @param Locator $locator
|
||||
* @param $useExistingData
|
||||
*/
|
||||
public function __construct(Mapper $mapper, Locator $locator, $useExistingData = false)
|
||||
{
|
||||
$this->mapper = $mapper;
|
||||
$this->locator = $locator;
|
||||
$this->useExistingData = $useExistingData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMapper()
|
||||
{
|
||||
return $this->mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columnFormatters
|
||||
*/
|
||||
public function setColumnFormatters($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = $columnFormatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnFormatters()
|
||||
{
|
||||
return $this->columnFormatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columnFormatters
|
||||
*/
|
||||
public function mergeColumnFormattersWith($columnFormatters)
|
||||
{
|
||||
$this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $modifiers
|
||||
*/
|
||||
public function setModifiers(array $modifiers)
|
||||
{
|
||||
$this->modifiers = $modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getModifiers()
|
||||
{
|
||||
return $this->modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $modifiers
|
||||
*/
|
||||
public function mergeModifiersWith(array $modifiers)
|
||||
{
|
||||
$this->modifiers = array_merge($this->modifiers, $modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Generator $generator
|
||||
* @return array
|
||||
*/
|
||||
public function guessColumnFormatters(Generator $generator)
|
||||
{
|
||||
$formatters = array();
|
||||
$nameGuesser = new Name($generator);
|
||||
$columnTypeGuesser = new ColumnTypeGuesser($generator);
|
||||
$fields = $this->mapper->fields();
|
||||
foreach ($fields as $fieldName => $field) {
|
||||
if ($field['primary'] === true) {
|
||||
continue;
|
||||
}
|
||||
if ($formatter = $nameGuesser->guessFormat($fieldName)) {
|
||||
$formatters[$fieldName] = $formatter;
|
||||
continue;
|
||||
}
|
||||
if ($formatter = $columnTypeGuesser->guessFormat($field)) {
|
||||
$formatters[$fieldName] = $formatter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$entityName = $this->mapper->entity();
|
||||
$entity = $this->mapper->build([]);
|
||||
$relations = $entityName::relations($this->mapper, $entity);
|
||||
foreach ($relations as $relation) {
|
||||
// We don't need any other relation here.
|
||||
if ($relation instanceof BelongsTo) {
|
||||
$fieldName = $relation->localKey();
|
||||
$entityName = $relation->entityName();
|
||||
$field = $fields[$fieldName];
|
||||
$required = $field['required'];
|
||||
|
||||
$locator = $this->locator;
|
||||
|
||||
$formatters[$fieldName] = function ($inserted) use ($required, $entityName, $locator) {
|
||||
if (!empty($inserted[$entityName])) {
|
||||
return $inserted[$entityName][mt_rand(0, count($inserted[$entityName]) - 1)]->get('id');
|
||||
}
|
||||
|
||||
if ($required && $this->useExistingData) {
|
||||
// We did not add anything like this, but it's required,
|
||||
// So let's find something existing in DB.
|
||||
$mapper = $locator->mapper($entityName);
|
||||
$records = $mapper->all()->limit(self::RELATED_FETCH_COUNT)->toArray();
|
||||
if (empty($records)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $records[mt_rand(0, count($records) - 1)]['id'];
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return $formatters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert one new record using the Entity class.
|
||||
*
|
||||
* @param $insertedEntities
|
||||
* @return string
|
||||
*/
|
||||
public function execute($insertedEntities)
|
||||
{
|
||||
$obj = $this->mapper->build([]);
|
||||
|
||||
$this->fillColumns($obj, $insertedEntities);
|
||||
$this->callMethods($obj, $insertedEntities);
|
||||
|
||||
$this->mapper->insert($obj);
|
||||
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $obj
|
||||
* @param $insertedEntities
|
||||
*/
|
||||
private function fillColumns($obj, $insertedEntities)
|
||||
{
|
||||
foreach ($this->columnFormatters as $field => $format) {
|
||||
if (null !== $format) {
|
||||
$value = is_callable($format) ? $format($insertedEntities, $obj) : $format;
|
||||
$obj->set($field, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $obj
|
||||
* @param $insertedEntities
|
||||
*/
|
||||
private function callMethods($obj, $insertedEntities)
|
||||
{
|
||||
foreach ($this->getModifiers() as $modifier) {
|
||||
$modifier($obj, $insertedEntities);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Faker\ORM\Spot;
|
||||
|
||||
use Spot\Locator;
|
||||
|
||||
/**
|
||||
* Service class for populating a database using the Spot ORM.
|
||||
*/
|
||||
class Populator
|
||||
{
|
||||
protected $generator;
|
||||
protected $locator;
|
||||
protected $entities = array();
|
||||
protected $quantities = array();
|
||||
|
||||
/**
|
||||
* Populator constructor.
|
||||
* @param \Faker\Generator $generator
|
||||
* @param Locator|null $locator
|
||||
*/
|
||||
public function __construct(\Faker\Generator $generator, Locator $locator = null)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
$this->locator = $locator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an order for the generation of $number records for $entity.
|
||||
*
|
||||
* @param $entityName string Name of Entity object to generate
|
||||
* @param $number int The number of entities to populate
|
||||
* @param $customColumnFormatters array
|
||||
* @param $customModifiers array
|
||||
* @param $useExistingData bool Should we use existing rows (e.g. roles) to populate relations?
|
||||
*/
|
||||
public function addEntity(
|
||||
$entityName,
|
||||
$number,
|
||||
$customColumnFormatters = array(),
|
||||
$customModifiers = array(),
|
||||
$useExistingData = false
|
||||
) {
|
||||
$mapper = $this->locator->mapper($entityName);
|
||||
if (null === $mapper) {
|
||||
throw new \InvalidArgumentException("No mapper can be found for entity " . $entityName);
|
||||
}
|
||||
$entity = new EntityPopulator($mapper, $this->locator, $useExistingData);
|
||||
|
||||
$entity->setColumnFormatters($entity->guessColumnFormatters($this->generator));
|
||||
if ($customColumnFormatters) {
|
||||
$entity->mergeColumnFormattersWith($customColumnFormatters);
|
||||
}
|
||||
$entity->mergeModifiersWith($customModifiers);
|
||||
|
||||
$this->entities[$entityName] = $entity;
|
||||
$this->quantities[$entityName] = $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the database using all the Entity classes previously added.
|
||||
*
|
||||
* @param Locator $locator A Spot locator
|
||||
*
|
||||
* @return array A list of the inserted PKs
|
||||
*/
|
||||
public function execute($locator = null)
|
||||
{
|
||||
if (null === $locator) {
|
||||
$locator = $this->locator;
|
||||
}
|
||||
if (null === $locator) {
|
||||
throw new \InvalidArgumentException("No entity manager passed to Spot Populator.");
|
||||
}
|
||||
|
||||
$insertedEntities = array();
|
||||
foreach ($this->quantities as $entityName => $number) {
|
||||
for ($i = 0; $i < $number; $i++) {
|
||||
$insertedEntities[$entityName][] = $this->entities[$entityName]->execute(
|
||||
$insertedEntities
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $insertedEntities;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user