GenerateEntityDoctrineCommand.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bundle\DoctrineBundle\Command;
  11. use Symfony\Component\Console\Input\InputArgument;
  12. use Symfony\Component\Console\Input\InputOption;
  13. use Symfony\Component\Console\Input\InputInterface;
  14. use Symfony\Component\Console\Output\OutputInterface;
  15. use Symfony\Component\Console\Output\Output;
  16. use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
  17. use Doctrine\ORM\Tools\EntityGenerator;
  18. use Doctrine\ORM\Mapping\ClassMetadataInfo;
  19. /**
  20. * Initialize a new Doctrine entity inside a bundle.
  21. *
  22. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  23. * @author Jonathan H. Wage <jonwage@gmail.com>
  24. */
  25. class GenerateEntityDoctrineCommand extends DoctrineCommand
  26. {
  27. protected function configure()
  28. {
  29. $this
  30. ->setName('doctrine:generate:entity')
  31. ->setDescription('Generate a new Doctrine entity inside a bundle.')
  32. ->addArgument('bundle', InputArgument::REQUIRED, 'The bundle to initialize the entity in.')
  33. ->addArgument('entity', InputArgument::REQUIRED, 'The entity class to initialize.')
  34. ->addOption('mapping-type', null, InputOption::VALUE_OPTIONAL, 'The mapping type to to use for the entity.', 'xml')
  35. ->addOption('fields', null, InputOption::VALUE_OPTIONAL, 'The fields to create with the new entity.')
  36. ->setHelp(<<<EOT
  37. The <info>doctrine:generate:entity</info> task initializes a new Doctrine entity inside a bundle:
  38. <info>./app/console doctrine:generate:entity "MyCustomBundle" "User\Group"</info>
  39. The above would initialize a new entity in the following entity namespace <info>Bundle\MyCustomBundle\Entity\User\Group</info>.
  40. You can also optionally specify the fields you want to generate in the new entity:
  41. <info>./app/console doctrine:generate:entity "MyCustomBundle" "User\Group" --fields="name:string(255) description:text"</info>
  42. EOT
  43. );
  44. }
  45. /**
  46. * @throws \InvalidArgumentException When the bundle doesn't end with Bundle (Example: "Bundle\MySampleBundle")
  47. */
  48. protected function execute(InputInterface $input, OutputInterface $output)
  49. {
  50. $bundle = $this->application->getKernel()->getBundle($input->getArgument('bundle'));
  51. $entity = $input->getArgument('entity');
  52. $fullEntityClassName = $bundle->getNamespace().'\\Entity\\'.$entity;
  53. $mappingType = $input->getOption('mapping-type');
  54. $class = new ClassMetadataInfo($fullEntityClassName);
  55. $class->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true));
  56. $class->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
  57. // Map the specified fields
  58. $fields = $input->getOption('fields');
  59. if ($fields) {
  60. $e = explode(' ', $fields);
  61. foreach ($e as $value) {
  62. $e = explode(':', $value);
  63. $name = $e[0];
  64. if (strlen($name)) {
  65. $type = isset($e[1]) ? $e[1] : 'string';
  66. preg_match_all('/(.*)\((.*)\)/', $type, $matches);
  67. $type = isset($matches[1][0]) ? $matches[1][0] : $type;
  68. $length = isset($matches[2][0]) ? $matches[2][0] : null;
  69. $class->mapField(array(
  70. 'fieldName' => $name,
  71. 'type' => $type,
  72. 'length' => $length
  73. ));
  74. }
  75. }
  76. }
  77. // Setup a new exporter for the mapping type specified
  78. $cme = new ClassMetadataExporter();
  79. $exporter = $cme->getExporter($mappingType);
  80. $entityPath = $bundle->getPath().'/Entity/'.$entity.'.php';
  81. if (file_exists($entityPath)) {
  82. throw new \RuntimeException(sprintf("Entity %s already exists.", $class->name));
  83. }
  84. if ('annotation' === $mappingType) {
  85. $exporter->setEntityGenerator($this->getEntityGenerator());
  86. $entityCode = $exporter->exportClassMetadata($class);
  87. $mappingPath = $mappingCode = false;
  88. } else {
  89. $mappingType = 'yaml' == $mappingType ? 'yml' : $mappingType;
  90. $mappingPath = $bundle->getPath().'/Resources/config/doctrine/metadata/orm/'.str_replace('\\', '.', $fullEntityClassName).'.dcm.'.$mappingType;
  91. $mappingCode = $exporter->exportClassMetadata($class);
  92. $entityGenerator = $this->getEntityGenerator();
  93. $entityCode = $entityGenerator->generateEntityClass($class);
  94. if (file_exists($mappingPath)) {
  95. throw new \RuntimeException(sprintf("Cannot generate entity when mapping <info>%s</info> already exists", $mappingPath));
  96. }
  97. }
  98. $output->writeln(sprintf('Generating entity for "<info>%s</info>"', $bundle->getName()));
  99. $output->writeln(sprintf(' > entity <comment>%s</comment> into <info>%s</info>', $fullEntityClassName, $entityPath));
  100. if (!is_dir($dir = dirname($entityPath))) {
  101. mkdir($dir, 0777, true);
  102. }
  103. file_put_contents($entityPath, $entityCode);
  104. if ($mappingPath) {
  105. $output->writeln(sprintf(' > mapping into <info>%s</info>', $mappingPath));
  106. if (!is_dir($dir = dirname($mappingPath))) {
  107. mkdir($dir, 0777, true);
  108. }
  109. file_put_contents($mappingPath, $mappingCode);
  110. }
  111. }
  112. }