/
ImportMappingDoctrineCommand.php
146 lines (122 loc) · 6.09 KB
/
ImportMappingDoctrineCommand.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<?php
namespace Doctrine\Bundle\DoctrineBundle\Command;
use Doctrine\ORM\Mapping\Driver\DatabaseDriver;
use Doctrine\ORM\Tools\Console\MetadataFilter;
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
use InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Import Doctrine ORM metadata mapping information from an existing database.
*/
class ImportMappingDoctrineCommand extends DoctrineCommand
{
/**
* {@inheritDoc}
*/
protected function configure()
{
$this
->setName('doctrine:mapping:import')
->addArgument('name', InputArgument::REQUIRED, 'The bundle or namespace to import the mapping information to')
->addArgument('mapping-type', InputArgument::OPTIONAL, 'The mapping type to export the imported mapping information to')
->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command')
->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command')
->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be mapped.')
->addOption('force', null, InputOption::VALUE_NONE, 'Force to overwrite existing mapping files.')
->addOption('path', null, InputOption::VALUE_REQUIRED, 'The path where the files would be generated (not used when a bundle is passed).')
->setDescription('Imports mapping information from an existing database')
->setHelp(<<<EOT
The <info>%command.name%</info> command imports mapping information
from an existing database:
Generate annotation mappings into the src/ directory using App as the namespace:
<info>php %command.full_name% App\\\Entity annotation --path=src/Entity</info>
Generate xml mappings into the config/doctrine/ directory using App as the namespace:
<info>php %command.full_name% App\\\Entity xml --path=config/doctrine</info>
Generate XML mappings into a bundle:
<info>php %command.full_name% "MyCustomBundle" xml</info>
You can also optionally specify which entity manager to import from with the
<info>--em</info> option:
<info>php %command.full_name% "MyCustomBundle" xml --em=default</info>
If you don't want to map every entity that can be found in the database, use the
<info>--filter</info> option. It will try to match the targeted mapped entity with the
provided pattern string.
<info>php %command.full_name% "MyCustomBundle" xml --filter=MyMatchedEntity</info>
Use the <info>--force</info> option, if you want to override existing mapping files:
<info>php %command.full_name% "MyCustomBundle" xml --force</info>
EOT
);
}
/**
* {@inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$type = $input->getArgument('mapping-type') ?: 'xml';
if ($type === 'yaml') {
$type = 'yml';
}
$namespaceOrBundle = $input->getArgument('name');
$bundles = $this->getContainer()->getParameter('kernel.bundles');
if (isset($bundles[$namespaceOrBundle])) {
$bundle = $this->getApplication()->getKernel()->getBundle($namespaceOrBundle);
$namespace = $bundle->getNamespace() . '\Entity';
$destPath = $bundle->getPath();
if ($type === 'annotation') {
$destPath .= '/Entity';
} else {
$destPath .= '/Resources/config/doctrine';
}
} else {
// assume a namespace has been passed
$namespace = $namespaceOrBundle;
$destPath = $input->getOption('path');
if ($destPath === null) {
throw new InvalidArgumentException('The --path option is required when passing a namespace (e.g. --path=src). If you intended to pass a bundle name, check your spelling.');
}
}
$cme = new ClassMetadataExporter();
$exporter = $cme->getExporter($type);
$exporter->setOverwriteExistingFiles($input->getOption('force'));
if ($type === 'annotation') {
$entityGenerator = $this->getEntityGenerator();
$exporter->setEntityGenerator($entityGenerator);
}
$em = $this->getEntityManager($input->getOption('em'), $input->getOption('shard'));
$databaseDriver = new DatabaseDriver($em->getConnection()->getSchemaManager());
$em->getConfiguration()->setMetadataDriverImpl($databaseDriver);
$emName = $input->getOption('em');
$emName = $emName ? $emName : 'default';
$cmf = new DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);
$metadata = $cmf->getAllMetadata();
$metadata = MetadataFilter::filter($metadata, $input->getOption('filter'));
if ($metadata) {
$output->writeln(sprintf('Importing mapping information from "<info>%s</info>" entity manager', $emName));
foreach ($metadata as $class) {
$className = $class->name;
$class->name = $namespace . '\\' . $className;
if ($type === 'annotation') {
$path = $destPath . '/' . str_replace('\\', '.', $className) . '.php';
} else {
$path = $destPath . '/' . str_replace('\\', '.', $className) . '.orm.' . $type;
}
$output->writeln(sprintf(' > writing <comment>%s</comment>', $path));
$code = $exporter->exportClassMetadata($class);
$dir = dirname($path);
if (! is_dir($dir)) {
mkdir($dir, 0775, true);
}
file_put_contents($path, $code);
chmod($path, 0664);
}
return 0;
}
$output->writeln('Database does not have any mapping information.');
$output->writeln('');
return 1;
}
}