SonataDumpDoctrineMetaCommand.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. /*
  3. * This file is part of the Sonata Project package.
  4. *
  5. * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  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 Sonata\CoreBundle\Command;
  11. use Doctrine\ORM\Mapping\ClassMetadata;
  12. use Gaufrette\Adapter\Local as LocalAdapter;
  13. use Gaufrette\Filesystem;
  14. use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
  15. use Symfony\Component\Console\Input\InputInterface;
  16. use Symfony\Component\Console\Input\InputOption;
  17. use Symfony\Component\Console\Output\OutputInterface;
  18. /**
  19. * Return useful data on the database schema.
  20. */
  21. class SonataDumpDoctrineMetaCommand extends ContainerAwareCommand
  22. {
  23. /**
  24. * @var array
  25. */
  26. protected $metadata;
  27. /**
  28. * {@inheritdoc}
  29. */
  30. protected function configure()
  31. {
  32. $this
  33. ->setName('sonata:core:dump-doctrine-metadata')
  34. ->setDefinition(array(
  35. new InputOption(
  36. 'entity-name',
  37. 'E',
  38. InputOption::VALUE_OPTIONAL,
  39. 'If entity-name is set, dump will only contain the specified entity and all its extended classes.',
  40. null
  41. ),
  42. new InputOption(
  43. 'regex',
  44. 'r',
  45. InputOption::VALUE_OPTIONAL,
  46. 'If regex is set, dump will only contain entities which name match the pattern.',
  47. null
  48. ),
  49. new InputOption(
  50. 'filename',
  51. 'f',
  52. InputOption::VALUE_OPTIONAL,
  53. 'If filename is specified, result will be dumped into this file under json format.',
  54. null
  55. ),
  56. ))
  57. ->setDescription('Get information on the current Doctrine\'s schema')
  58. ;
  59. }
  60. /**
  61. * {@inheritdoc}
  62. */
  63. protected function initialize(InputInterface $input, OutputInterface $output)
  64. {
  65. $output->writeln('Initialising Doctrine metadata.');
  66. $manager = $this->getContainer()->get('doctrine')->getManager();
  67. $metadata = $manager->getMetadataFactory()->getAllMetadata();
  68. $allowedMeta = $this->filterMetadata($metadata, $input, $output);
  69. /** @var ClassMetadata $meta */
  70. foreach ($allowedMeta as $meta) {
  71. $this->metadata[$meta->getName()] = $this->normalizeDoctrineORMMeta($meta);
  72. }
  73. }
  74. /**
  75. * {@inheritdoc}
  76. */
  77. protected function execute(InputInterface $input, OutputInterface $output)
  78. {
  79. if (!$this->metadata) {
  80. $output->writeln('<error>No meta was found</error>');
  81. return 1;
  82. }
  83. $this->dumpMetadata($this->metadata, $input, $output);
  84. return 0;
  85. }
  86. /**
  87. * Display the list of entities handled by Doctrine and their fields.
  88. *
  89. * @param array $metadata
  90. * @param InputInterface $input
  91. * @param OutputInterface $output
  92. */
  93. private function dumpMetadata(array $metadata, InputInterface $input, OutputInterface $output)
  94. {
  95. foreach ($metadata as $name => $meta) {
  96. $output->writeln(sprintf('<info>%s</info>', $name));
  97. foreach ($meta['fields'] as $fieldName => $columnName) {
  98. $output->writeln(sprintf(' <comment>></comment> %s <info>=></info> %s', $fieldName, $columnName));
  99. }
  100. }
  101. $output->writeln('---------------');
  102. $output->writeln('---- END ----');
  103. $output->writeln('---------------');
  104. $output->writeln('');
  105. if ($input->getOption('filename')) {
  106. $directory = dirname($input->getOption('filename'));
  107. $filename = basename($input->getOption('filename'));
  108. if (empty($directory) || $directory === '.') {
  109. $directory = getcwd();
  110. }
  111. $adapter = new LocalAdapter($directory, true);
  112. $fileSystem = new Filesystem($adapter);
  113. $success = $fileSystem->write($filename, json_encode($metadata), true);
  114. if ($success) {
  115. $output->writeLn(sprintf('<info>File %s/%s successfully created</info>', $directory, $filename));
  116. } else {
  117. $output->writeLn(sprintf('<error>File %s/%s could not be created</error>', $directory, $filename));
  118. }
  119. }
  120. }
  121. /**
  122. * @param array $metadata
  123. * @param InputInterface $input
  124. * @param OutputInterface $output
  125. *
  126. * @return array
  127. */
  128. private function filterMetadata(array $metadata, InputInterface $input, OutputInterface $output)
  129. {
  130. $baseEntity = $input->getOption('entity-name');
  131. $regex = $input->getOption('regex');
  132. if ($baseEntity) {
  133. $allowedMeta = array_filter(
  134. $metadata,
  135. function ($meta) use ($baseEntity) {
  136. /* @var \Doctrine\ORM\Mapping\ClassMetadata $meta */
  137. return $meta->rootEntityName === $baseEntity;
  138. }
  139. );
  140. } elseif ($regex) {
  141. $allowedMeta = array_filter(
  142. $metadata,
  143. function ($meta) use ($regex) {
  144. /* @var \Doctrine\ORM\Mapping\ClassMetadata $meta */
  145. return preg_match($regex, $meta->rootEntityName);
  146. }
  147. );
  148. } else {
  149. $allowedMeta = $metadata;
  150. }
  151. return $allowedMeta;
  152. }
  153. /**
  154. * @param ClassMetadata $meta
  155. *
  156. * @return array
  157. */
  158. private function normalizeDoctrineORMMeta(ClassMetadata $meta)
  159. {
  160. $normalizedMeta = array();
  161. $fieldMappings = $meta->fieldMappings;
  162. $normalizedMeta['table'] = $meta->table['name'];
  163. foreach ($fieldMappings as $field) {
  164. $normalizedMeta['fields'][$field['fieldName']] = isset($field['columnName']) ? $field['columnName'] : null;
  165. }
  166. return $normalizedMeta;
  167. }
  168. }