Selaa lähdekoodia

[DoctrineBundle] First round of cleanup the Command namespace in DoctrineBundle

Benjamin Eberlei 14 vuotta sitten
vanhempi
commit
bdbfb44a96

+ 0 - 105
src/Symfony/Bundle/DoctrineBundle/Command/ConvertDoctrine1SchemaDoctrineCommand.php

@@ -1,105 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Bundle\DoctrineBundle\Command;
-
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Output\Output;
-use Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand;
-use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
-use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
-use Doctrine\ORM\Mapping\Driver\DatabaseDriver;
-use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
-use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
-use Doctrine\ORM\Tools\ConvertDoctrine1Schema;
-
-/**
- * Convert a Doctrine 1 schema to Doctrine 2 mapping files
- *
- * @author Fabien Potencier <fabien.potencier@symfony-project.com>
- * @author Jonathan H. Wage <jonwage@gmail.com>
- */
-class ConvertDoctrine1SchemaDoctrineCommand extends DoctrineCommand
-{
-    protected function configure()
-    {
-        $this
-            ->setName('doctrine:mapping:convert-d1-schema')
-            ->setDescription('Convert a Doctrine 1 schema to Doctrine 2 mapping files.')
-            ->addArgument('d1-schema', InputArgument::REQUIRED, 'Path to the Doctrine 1 schema files.')
-            ->addArgument('bundle', InputArgument::REQUIRED, 'The bundle to write the converted mapping information to.')
-            ->addArgument('mapping-type', InputArgument::OPTIONAL, 'The mapping type to export the converted mapping information to.')
-            ->setHelp(<<<EOT
-The <info>doctrine:mapping:convert-d1-schema</info> command converts a Doctrine 1 schema to Doctrine 2 mapping files:
-
-  <info>./app/console doctrine:mapping:convert-d1-schema /path/to/doctrine1schema "BundleMyBundle" xml</info>
-
-Each Doctrine 1 model will have its own XML mapping file located in <info>Bundle/MyBundle/config/doctrine/metadata</info>.
-EOT
-        );
-    }
-
-    /**
-     * @see Command
-     */
-    protected function execute(InputInterface $input, OutputInterface $output)
-    {
-        $bundle = $this->application->getKernel()->getBundle($input->getArgument('bundle'));
-
-        $destPath = $bundle->getPath();
-        $type = $input->getArgument('mapping-type') ? $input->getArgument('mapping-type') : 'xml';
-        if ('annotation' === $type) {
-            $destPath .= '/Entity';
-        } else {
-            $destPath .= '/Resources/config/doctrine/metadata/orm';
-        }
-
-        // adjust so file naming works
-        if ('yaml' === $type) {
-            $type = 'yml';
-        }
-
-        $cme = new ClassMetadataExporter();
-        $exporter = $cme->getExporter($type);
-
-        if ('annotation' === $type) {
-            $entityGenerator = $this->getEntityGenerator();
-            $exporter->setEntityGenerator($entityGenerator);
-        }
-
-        $converter = new ConvertDoctrine1Schema($input->getArgument('d1-schema'));
-        $metadata = $converter->getMetadata();
-
-        if ($metadata) {
-            $output->writeln(sprintf('Converting Doctrine 1 schema "<info>%s</info>"', $input->getArgument('d1-schema')));
-            foreach ($metadata as $class) {
-                $className = $class->name;
-                $class->name = $bundle->getNamespace().'\\Entity\\'.$className;
-                if ('annotation' === $type) {
-                    $path = $destPath.'/'.$className.'.php';
-                } else {
-                    $path = $destPath.'/'.str_replace('\\', '.', $class->name).'.dcm.'.$type;
-                }
-                $output->writeln(sprintf('  > writing <comment>%s</comment>', $path));
-                $code = $exporter->exportClassMetadata($class);
-                if (!is_dir($dir = dirname($path))) {
-                    mkdir($dir, 0777, true);
-                }
-                file_put_contents($path, $code);
-            }
-        } else {
-            $output->writeln('Database does not have any mapping information.'.PHP_EOL, 'ERROR');
-        }
-    }
-}

+ 2 - 20
src/Symfony/Bundle/DoctrineBundle/Command/CreateDatabaseDoctrineCommand.php

@@ -49,26 +49,8 @@ EOT
 
     protected function execute(InputInterface $input, OutputInterface $output)
     {
-        $found = false;
-        $connections = $this->getDoctrineConnections();
-        foreach ($connections as $name => $connection) {
-            if ($input->getOption('connection') && $name != $input->getOption('connection')) {
-                continue;
-            }
-            $this->createDatabaseForConnection($connection, $output);
-            $found = true;
-        }
-        if (false === $found) {
-            if ($input->getOption('connection')) {
-                throw new \InvalidArgumentException(sprintf('<error>Could not find a connection named <comment>%s</comment></error>', $input->getOption('connection')));
-            } else {
-                throw new \InvalidArgumentException(sprintf('<error>Could not find any configured connections</error>', $input->getOption('connection')));
-            }
-        }
-    }
-
-    protected function createDatabaseForConnection(Connection $connection, OutputInterface $output)
-    {
+        $connection = $this->getDoctrineConnection($intput->getOption('connection'));
+        
         $params = $connection->getParams();
         $name = isset($params['path']) ? $params['path']:$params['dbname'];
 

+ 24 - 50
src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php

@@ -30,20 +30,23 @@ use Doctrine\ORM\Tools\EntityGenerator;
 /**
  * Base class for Doctrine console commands to extend from.
  *
+ * Provides some helper and convenience methods to configure doctrine commands in the context of bundles
+ * and multiple connections/entity managers.
+ *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
 abstract class DoctrineCommand extends Command
 {
+    /**
+     * Convenience method to push the helper sets of a given entity manager into the application.
+     * 
+     * @param Application $application
+     * @param string $emName
+     */
     public static function setApplicationEntityManager(Application $application, $emName)
     {
         $container = $application->getKernel()->getContainer();
-        $emName = $emName ? $emName : 'default';
-        $emServiceName = sprintf('doctrine.orm.%s_entity_manager', $emName);
-        if (!$container->has($emServiceName)) {
-            throw new \InvalidArgumentException(sprintf('Could not find Doctrine EntityManager named "%s"', $emName));
-        }
-
-        $em = $container->get($emServiceName);
+        $em = self::getEntityManager($container, $emName);
         $helperSet = $application->getHelperSet();
         $helperSet->set(new ConnectionHelper($em->getConnection()), 'db');
         $helperSet->set(new EntityManagerHelper($em), 'em');
@@ -52,7 +55,7 @@ abstract class DoctrineCommand extends Command
     public static function setApplicationConnection(Application $application, $connName)
     {
         $container = $application->getKernel()->getContainer();
-        $connName = $connName ? $connName : 'default';
+        $connName = $connName ? $connName : $container->getParameter('doctrine.dbal.default_connection');
         $connServiceName = sprintf('doctrine.dbal.%s_connection', $connName);
         if (!$container->has($connServiceName)) {
             throw new \InvalidArgumentException(sprintf('Could not find Doctrine Connection named "%s"', $connName));
@@ -75,60 +78,31 @@ abstract class DoctrineCommand extends Command
         return $entityGenerator;
     }
 
-    protected function getEntityManager($name = null)
+    protected static function getEntityManager($container, $name = null)
     {
-        $name = $name ? $name : 'default';
+        $name = $name ? $name : $container->getParameter('doctrine.orm.default_entity_manager');
         $serviceName = sprintf('doctrine.orm.%s_entity_manager', $name);
-        if (!$this->container->has($serviceName)) {
+        if (!$container->has($serviceName)) {
             throw new \InvalidArgumentException(sprintf('Could not find Doctrine EntityManager named "%s"', $name));
         }
 
-        return $this->container->get($serviceName);
-    }
-
-    protected function runCommand($name, array $input = array())
-    {
-        $application = new Application($this->container->get('kernel'));
-        $arguments = array();
-        $arguments = array_merge(array($name), $input);
-        $input = new ArrayInput($arguments);
-        $application->setAutoExit(false);
-        $application->run($input);
+        return $container->get($serviceName);
     }
 
     /**
-     * TODO: Better way to do these functions?
+     * Get a doctrine dbal connection by symfony name.
      *
-     * @return Connection[] An array of Connections
+     * @param string $name
+     * @return Doctrine\DBAL\Connection
      */
-    protected function getDoctrineConnections()
+    protected function getDoctrineConnection($name)
     {
-        $connections = array();
-        $ids = $this->container->getServiceIds();
-        foreach ($ids as $id) {
-            preg_match('/^doctrine\.dbal\.(.*)_connection$/', $id, $matches);
-            if ($matches) {
-                $name = $matches[1];
-                $connections[$name] = $this->container->get($id);
-            }
+        $connectionName = $name ?: $this->container->getParameter('doctrine.dbal.default_connection');
+        $connectionName = sprintf('doctrine.dbal.%s_connection', $connectionName);
+        if (!$this->container->has($connectionName)) {
+            throw new \InvalidArgumentException(sprintf('<error>Could not find a connection named <comment>%s</comment></error>', $name));
         }
-
-        return $connections;
-    }
-
-    protected function getDoctrineEntityManagers()
-    {
-        $entityManagers = array();
-        $ids = $this->container->getServiceIds();
-        foreach ($ids as $id) {
-            preg_match('/^doctrine\.orm\.(.*)_entity_manager$/', $id, $matches);
-            if ($matches) {
-                $name = $matches[1];
-                $entityManagers[$name] = $this->container->get($id);
-            }
-        }
-
-        return $entityManagers;
+        return $this->container->get($connectionName);
     }
 
     protected function getDoctrineEntityManagers()

+ 24 - 27
src/Symfony/Bundle/DoctrineBundle/Command/DropDatabaseDoctrineCommand.php

@@ -35,49 +35,46 @@ class DropDatabaseDoctrineCommand extends DoctrineCommand
             ->setName('doctrine:database:drop')
             ->setDescription('Drop the configured databases.')
             ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command.')
+            ->addOption('force', null, InputOption::VALUE_NONE, 'Set this parameter to execute this action.')
             ->setHelp(<<<EOT
 The <info>doctrine:database:drop</info> command drops the default connections database:
 
   <info>./app/console doctrine:database:drop</info>
 
+The --force parameter has to be used to actually drop the database.
+
 You can also optionally specify the name of a connection to drop the database for:
 
   <info>./app/console doctrine:database:drop --connection=default</info>
+
+<error>Be careful: All data in a given database will be lost when executing this command.</error>
 EOT
         );
     }
 
     protected function execute(InputInterface $input, OutputInterface $output)
     {
-        $found = false;
-        $connections = $this->getDoctrineConnections();
-        foreach ($connections as $name => $connection) {
-            if ($input->getOption('connection') && $name != $input->getOption('connection')) {
-                continue;
-            }
-            $this->dropDatabaseForConnection($connection, $output);
-            $found = true;
-        }
-        if (false === $found) {
-            if ($input->getOption('connection')) {
-                throw new \InvalidArgumentException(sprintf('<error>Could not find a connection named <comment>%s</comment></error>', $input->getOption('connection')));
-            } else {
-                throw new \InvalidArgumentException(sprintf('<error>Could not find any configured connections</error>', $input->getOption('connection')));
-            }
-        }
-    }
-
-    protected function dropDatabaseForConnection(Connection $connection, OutputInterface $output)
-    {
+        $connection = $this->getDoctrineConnection($intput->getOption('connection'));
+        
         $params = $connection->getParams();
-        $name = isset($params['path']) ? $params['path']:$params['dbname'];
 
-        try {
-            $connection->getSchemaManager()->dropDatabase($name);
-            $output->writeln(sprintf('<info>Dropped database for connection named <comment>%s</comment></info>', $name));
-        } catch (\Exception $e) {
-            $output->writeln(sprintf('<error>Could not drop database for connection named <comment>%s</comment></error>', $name));
-            $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
+        $name = isset($params['path'])?$params['path']:(isset($params['dbname'])?$params['dbname']:false);
+
+        if (!$name) {
+            throw new \InvalidArgumentException("Connection does not contain a 'path' or 'dbname' parameter and cannot be dropped.");
+        }
+
+        if ($input->getOption('force')) {
+            try {
+                $connection->getSchemaManager()->dropDatabase($name);
+                $output->writeln(sprintf('<info>Dropped database for connection named <comment>%s</comment></info>', $name));
+            } catch (\Exception $e) {
+                $output->writeln(sprintf('<error>Could not drop database for connection named <comment>%s</comment></error>', $name));
+                $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
+            }
+        } else {
+            $output->writeln(sprintf('<info>Would drop the database named <comment>%</comment>.</info>', $name));
+            $output->writeln(sprintf('<error>All data will be lost!</error>', $name));
         }
     }
 }

+ 12 - 22
src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php

@@ -32,54 +32,44 @@ class GenerateEntitiesDoctrineCommand extends DoctrineCommand
         $this
             ->setName('doctrine:generate:entities')
             ->setDescription('Generate entity classes and method stubs from your mapping information.')
-            ->addOption('bundle', null, InputOption::VALUE_OPTIONAL, 'The bundle to initialize the entity or entities in.')
-            ->addOption('entity', null, InputOption::VALUE_OPTIONAL, 'The entity class to initialize (requires bundle parameter).')
+            ->addOption('bundle', null, InputOption::VALUE_REQUIRED, 'The bundle to initialize the entity or entities in.')
+            ->addOption('entity', null, InputOption::VALUE_OPTIONAL, 'The entity class to initialize (shortname without namespace).')
             ->setHelp(<<<EOT
 The <info>doctrine:generate:entities</info> command generates entity classes and method stubs from your mapping information:
 
-  <info>./app/console doctrine:generate:entities</info>
+You have to limit generation of entities to an individual bundle:
 
-The above would generate entity classes for all bundles.
-
-You can also optionally limit generation to entities within an individual bundle:
-
-  <info>./app/console doctrine:generate:entities --bundle="Bundle/MyCustomBundle"</info>
+  <info>./app/console doctrine:generate:entities --bundle="MyCustomBundle"</info>
 
 Alternatively, you can limit generation to a single entity within a bundle:
 
-  <info>./app/console doctrine:generate:entities --bundle="Bundle/MyCustomBundle" --entity="User"</info>
+  <info>./app/console doctrine:generate:entities --bundle="MyCustomBundle" --entity="User"</info>
+
+You have to specifiy the shortname (without namespace) of the entity you want to filter for.
 EOT
         );
     }
 
     protected function execute(InputInterface $input, OutputInterface $output)
     {
-        $filterBundle = $input->getOption('bundle') ? str_replace('/', '\\', $input->getOption('bundle')) : false;
-        $filterEntity = $filterBundle ? $filterBundle . '\\Entity\\' . str_replace('/', '\\', $input->getOption('entity')) : false;
-
-        if (!isset($filterBundle) && isset($filterEntity)) {
-            throw new \InvalidArgumentException(sprintf('Unable to specify an entity without also specifying a bundle.'));
-        }
+        $filterEntity = $input->getOption('entity');
 
         $entityGenerator = $this->getEntityGenerator();
         foreach ($this->application->getKernel()->getBundles() as $bundle) {
-
-            // retrieve the full bundle classname
-            $class = get_class($bundle);
-
-            if ($filterBundle && $filterBundle != $class) {
+            /* @var $bundle Bundle */
+            if ($input->getOption('bundle') != $bundle->getName()) {
                 continue;
             }
 
             // transform classname to a path and substract it to get the destination
-            $path = dirname(str_replace('\\', '/', $class));
+            $path = dirname(str_replace('\\', '/', $bundle->getNamespace()));
             $destination = str_replace('/'.$path, "", $bundle->getPath());
 
             if ($metadatas = $this->getBundleMetadatas($bundle)) {
                 $output->writeln(sprintf('Generating entities for "<info>%s</info>"', $class));
 
                 foreach ($metadatas as $metadata) {
-                    if ($filterEntity && strpos($metadata->name, $filterEntity) !== 0) {
+                    if ($filterEntity && $metadata->reflClass->getShortName() == $filterEntity) {
                         continue;
                     }
                     $output->writeln(sprintf('  > generating <comment>%s</comment>', $metadata->name));

+ 5 - 1
src/Symfony/Bundle/DoctrineBundle/Command/GenerateProxiesDoctrineCommand.php

@@ -34,9 +34,13 @@ class GenerateProxiesDoctrineCommand extends GenerateProxiesCommand
             ->setName('doctrine:generate:proxies')
             ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command.')
             ->setHelp(<<<EOT
-The <info>doctrine:generate:proxies</info> command generates proxy classes for your entities:
+The <info>doctrine:generate:proxies</info> command generates proxy classes for your default entity manager:
 
   <info>./app/console doctrine:generate:proxies</info>
+
+You can specify the entity manager you want to generate the proxies for:
+
+  <info>./app/console doctrine:generate:proxies --em=name</info>
 EOT
         );
     }

+ 56 - 0
src/Symfony/Bundle/DoctrineBundle/Tests/Command/DoctrineCommandTest.php

@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony framework.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Symfony\Bundle\DoctrineBundle\Tests\Command;
+
+use Symfony\Bundle\DoctrineBundle\Tests\TestCase;
+use Symfony\Bundle\FrameworkBundle\Console\Application;
+use Symfony\Bundle\DoctrineBundle\Command\DoctrineCommand;
+
+class DoctrineCommandTest extends TestCase
+{
+    private $em;
+
+    public function testSetApplicationEntityManager()
+    {
+        $kernel = $this->createKernelMock('test');
+
+        $application = new Application($kernel);
+        DoctrineCommand::setApplicationEntityManager($application, 'test');
+
+        $this->assertTrue($application->getHelperSet()->has('em'));
+        $this->assertTrue($application->getHelperSet()->has('db'));
+    }
+
+    public function testSetApplicationConnection()
+    {
+        $kernel = $this->createKernelMock('test');
+
+        $application = new Application($kernel);
+        DoctrineCommand::setApplicationConnection($application, 'test');
+
+        $this->assertFalse($application->getHelperSet()->has('em'));
+        $this->assertTrue($application->getHelperSet()->has('db'));
+    }
+
+    public function createKernelMock($name)
+    {
+        $this->em = $this->createTestEntityManager();
+        $kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
+        $container = new \Symfony\Component\DependencyInjection\Container();
+        $container->set(sprintf('doctrine.orm.%s_entity_manager', $name), $this->em);
+        $container->set(sprintf('doctrine.dbal.%s_connection', $name), $this->em->getConnection());
+        $kernel->expects($this->once())->method('getContainer')->will($this->returnValue($container));
+        $kernel->expects($this->once())->method('getBundles')->will($this->returnValue(array()));
+
+        return $kernel;
+    }
+}

+ 3 - 0
src/Symfony/Bundle/FrameworkBundle/Command/Command.php

@@ -25,6 +25,9 @@ use Symfony\Component\Console\Command\Command as BaseCommand;
  */
 abstract class Command extends BaseCommand
 {
+    /**
+     * @var \Symfony\Component\DependencyInjection\ContainerInterface
+     */
     protected $container;
 
     protected function initialize(InputInterface $input, OutputInterface $output)