3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 * This software consists of voluntary contributions made by many individuals
16 * and is licensed under the MIT license. For more information, see
17 * <http://www.doctrine-project.org>.
20 namespace Doctrine\ORM\Tools\Console\Command;
22 use Symfony\Component\Console\Input\InputArgument,
23 Symfony\Component\Console\Input\InputOption,
24 Symfony\Component\Console,
25 Doctrine\ORM\Tools\Console\MetadataFilter,
26 Doctrine\ORM\Tools\Export\ClassMetadataExporter,
27 Doctrine\ORM\Tools\EntityGenerator,
28 Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
31 * Command to convert your mapping information between the various formats.
34 * @link www.doctrine-project.org
36 * @author Benjamin Eberlei <kontakt@beberlei.de>
37 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
38 * @author Jonathan Wage <jonwage@gmail.com>
39 * @author Roman Borschel <roman@code-factory.org>
41 class ConvertMappingCommand extends Console\Command\Command
44 * @see Console\Command\Command
46 protected function configure()
49 ->setName('orm:convert-mapping')
50 ->setDescription('Convert mapping information between supported formats.')
51 ->setDefinition(array(
53 'filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
54 'A string pattern used to match entities that should be processed.'
57 'to-type', InputArgument::REQUIRED, 'The mapping type to be converted.'
60 'dest-path', InputArgument::REQUIRED,
61 'The path to generate your entities classes.'
64 'force', null, InputOption::VALUE_NONE,
65 'Force to overwrite existing mapping files.'
68 'from-database', null, null, 'Whether or not to convert mapping information from existing database.'
71 'extend', null, InputOption::VALUE_OPTIONAL,
72 'Defines a base class to be extended by generated entity classes.'
75 'num-spaces', null, InputOption::VALUE_OPTIONAL,
76 'Defines the number of indentation spaces', 4
79 'namespace', null, InputOption::VALUE_OPTIONAL,
80 'Defines a namespace for the generated entity classes, if converted from database.'
84 Convert mapping information between supported formats.
86 This is an execute <info>one-time</info> command. It should not be necessary for
87 you to call this method multiple times, escpecially when using the <comment>--from-database</comment>
90 Converting an existing databsae schema into mapping files only solves about 70-80%
91 of the necessary mapping information. Additionally the detection from an existing
92 database cannot detect inverse associations, inheritance types,
93 entities with foreign keys as primary keys and many of the
94 semantical operations on associations such as cascade.
96 <comment>Hint:</comment> There is no need to convert YAML or XML mapping files to annotations
97 every time you make changes. All mapping drivers are first class citizens
98 in Doctrine 2 and can be used as runtime mapping for the ORM.
104 * @see Console\Command\Command
106 protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
108 $em = $this->getHelper('em')->getEntityManager();
110 if ($input->getOption('from-database') === true) {
111 $databaseDriver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
112 $em->getConnection()->getSchemaManager()
115 $em->getConfiguration()->setMetadataDriverImpl(
119 if (($namespace = $input->getOption('namespace')) !== null) {
120 $databaseDriver->setNamespace($namespace);
124 $cmf = new DisconnectedClassMetadataFactory();
125 $cmf->setEntityManager($em);
126 $metadata = $cmf->getAllMetadata();
127 $metadata = MetadataFilter::filter($metadata, $input->getOption('filter'));
129 // Process destination directory
130 if ( ! is_dir($destPath = $input->getArgument('dest-path'))) {
131 mkdir($destPath, 0777, true);
133 $destPath = realpath($destPath);
135 if ( ! file_exists($destPath)) {
136 throw new \InvalidArgumentException(
137 sprintf("Mapping destination directory '<info>%s</info>' does not exist.", $input->getArgument('dest-path'))
139 } else if ( ! is_writable($destPath)) {
140 throw new \InvalidArgumentException(
141 sprintf("Mapping destination directory '<info>%s</info>' does not have write permissions.", $destPath)
145 $toType = strtolower($input->getArgument('to-type'));
147 $exporter = $this->getExporter($toType, $destPath);
148 $exporter->setOverwriteExistingFiles( ($input->getOption('force') !== false) );
150 if ($toType == 'annotation') {
151 $entityGenerator = new EntityGenerator();
152 $exporter->setEntityGenerator($entityGenerator);
154 $entityGenerator->setNumSpaces($input->getOption('num-spaces'));
156 if (($extend = $input->getOption('extend')) !== null) {
157 $entityGenerator->setClassToExtend($extend);
161 if (count($metadata)) {
162 foreach ($metadata as $class) {
163 $output->write(sprintf('Processing entity "<info>%s</info>"', $class->name) . PHP_EOL);
166 $exporter->setMetadata($metadata);
169 $output->write(PHP_EOL . sprintf(
170 'Exporting "<info>%s</info>" mapping information to "<info>%s</info>"' . PHP_EOL, $toType, $destPath
173 $output->write('No Metadata Classes to process.' . PHP_EOL);
177 protected function getExporter($toType, $destPath)
179 $cme = new ClassMetadataExporter();
181 return $cme->getExporter($toType, $destPath);