PageRenderTime 27ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Faker/ORM/Doctrine/EntityPopulator.php

https://gitlab.com/sarelvdwalt/Faker
PHP | 197 lines | 140 code | 33 blank | 24 comment | 16 complexity | 2e67cbdc0bf35ae35115ff15e90d91cc MD5 | raw file
  1. <?php
  2. namespace Faker\ORM\Doctrine;
  3. use Doctrine\Common\Persistence\ObjectManager;
  4. use Doctrine\ORM\EntityManagerInterface;
  5. use Doctrine\ORM\Mapping\ClassMetadata;
  6. /**
  7. * Service class for populating a table through a Doctrine Entity class.
  8. */
  9. class EntityPopulator
  10. {
  11. /**
  12. * @var ClassMetadata
  13. */
  14. protected $class;
  15. /**
  16. * @var array
  17. */
  18. protected $columnFormatters = array();
  19. /**
  20. * @var array
  21. */
  22. protected $modifiers = array();
  23. /**
  24. * Class constructor.
  25. *
  26. * @param ClassMetadata $class
  27. */
  28. public function __construct(ClassMetadata $class)
  29. {
  30. $this->class = $class;
  31. }
  32. /**
  33. * @return string
  34. */
  35. public function getClass()
  36. {
  37. return $this->class->getName();
  38. }
  39. public function setColumnFormatters($columnFormatters)
  40. {
  41. $this->columnFormatters = $columnFormatters;
  42. }
  43. public function getColumnFormatters()
  44. {
  45. return $this->columnFormatters;
  46. }
  47. public function mergeColumnFormattersWith($columnFormatters)
  48. {
  49. $this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters);
  50. }
  51. public function setModifiers(array $modifiers)
  52. {
  53. $this->modifiers = $modifiers;
  54. }
  55. public function getModifiers()
  56. {
  57. return $this->modifiers;
  58. }
  59. public function mergeModifiersWith(array $modifiers)
  60. {
  61. $this->modifiers = array_merge($this->modifiers, $modifiers);
  62. }
  63. public function guessColumnFormatters(\Faker\Generator $generator)
  64. {
  65. $formatters = array();
  66. $nameGuesser = new \Faker\Guesser\Name($generator);
  67. $columnTypeGuesser = new ColumnTypeGuesser($generator);
  68. foreach ($this->class->getFieldNames() as $fieldName) {
  69. if ($this->class->isIdentifier($fieldName) || !$this->class->hasField($fieldName)) {
  70. continue;
  71. }
  72. $size = isset($this->class->fieldMappings[$fieldName]['length']) ? $this->class->fieldMappings[$fieldName]['length'] : null;
  73. if ($formatter = $nameGuesser->guessFormat($fieldName, $size)) {
  74. $formatters[$fieldName] = $formatter;
  75. continue;
  76. }
  77. if ($formatter = $columnTypeGuesser->guessFormat($fieldName, $this->class)) {
  78. $formatters[$fieldName] = $formatter;
  79. continue;
  80. }
  81. }
  82. foreach ($this->class->getAssociationNames() as $assocName) {
  83. if ($this->class->isCollectionValuedAssociation($assocName)) {
  84. continue;
  85. }
  86. $relatedClass = $this->class->getAssociationTargetClass($assocName);
  87. $unique = $optional = false;
  88. $mappings = $this->class->getAssociationMappings();
  89. foreach ($mappings as $mapping) {
  90. if ($mapping['targetEntity'] == $relatedClass) {
  91. if ($mapping['type'] == ClassMetadata::ONE_TO_ONE) {
  92. $unique = true;
  93. $optional = isset($mapping['joinColumns'][0]['nullable']) ? $mapping['joinColumns'][0]['nullable'] : false;
  94. break;
  95. }
  96. }
  97. }
  98. $index = 0;
  99. $formatters[$assocName] = function ($inserted) use ($relatedClass, &$index, $unique, $optional) {
  100. if (isset($inserted[$relatedClass])) {
  101. if ($unique) {
  102. $related = null;
  103. if (isset($inserted[$relatedClass][$index]) || !$optional) {
  104. $related = $inserted[$relatedClass][$index];
  105. }
  106. $index++;
  107. return $related;
  108. }
  109. return $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)];
  110. }
  111. return null;
  112. };
  113. }
  114. return $formatters;
  115. }
  116. /**
  117. * Insert one new record using the Entity class.
  118. */
  119. public function execute(ObjectManager $manager, $insertedEntities, $generateId = false)
  120. {
  121. $obj = $this->class->newInstance();
  122. $this->fillColumns($obj, $insertedEntities);
  123. $this->callMethods($obj, $insertedEntities);
  124. if ($generateId) {
  125. $idsName = $this->class->getIdentifier();
  126. foreach ($idsName as $idName) {
  127. $id = $this->generateId($obj, $idName, $manager);
  128. $this->class->reflFields[$idName]->setValue($obj, $id);
  129. }
  130. }
  131. $manager->persist($obj);
  132. return $obj;
  133. }
  134. private function fillColumns($obj, $insertedEntities)
  135. {
  136. foreach ($this->columnFormatters as $field => $format) {
  137. if (null !== $format) {
  138. $value = is_callable($format) ? $format($insertedEntities, $obj) : $format;
  139. $this->class->reflFields[$field]->setValue($obj, $value);
  140. }
  141. }
  142. }
  143. private function callMethods($obj, $insertedEntities)
  144. {
  145. foreach ($this->getModifiers() as $modifier) {
  146. $modifier($obj, $insertedEntities);
  147. }
  148. }
  149. private function generateId($obj, $column, EntityManagerInterface $manager)
  150. {
  151. /* @var $repository \Doctrine\ORM\EntityRepository */
  152. $repository = $manager->getRepository(get_class($obj));
  153. $result = $repository->createQueryBuilder('e')
  154. ->select(sprintf('e.%s', $column))
  155. ->getQuery()
  156. ->getResult();
  157. $ids = array_map('current', $result);
  158. $id = null;
  159. do {
  160. $id = mt_rand();
  161. } while (in_array($id, $ids));
  162. return $id;
  163. }
  164. }