From bdbfb44a96765a8b3d2a0898996160c1a2cc1c13 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Thu, 27 Jan 2011 00:28:53 +0100 Subject: [PATCH] [DoctrineBundle] First round of cleanup the Command namespace in DoctrineBundle --- .../ConvertDoctrine1SchemaDoctrineCommand.php | 105 ------------------ .../Command/CreateDatabaseDoctrineCommand.php | 22 +--- .../Command/DoctrineCommand.php | 74 ++++-------- .../Command/DropDatabaseDoctrineCommand.php | 51 ++++----- .../GenerateEntitiesDoctrineCommand.php | 34 ++---- .../GenerateProxiesDoctrineCommand.php | 6 +- .../Tests/Command/DoctrineCommandTest.php | 56 ++++++++++ .../FrameworkBundle/Command/Command.php | 3 + 8 files changed, 126 insertions(+), 225 deletions(-) delete mode 100644 src/Symfony/Bundle/DoctrineBundle/Command/ConvertDoctrine1SchemaDoctrineCommand.php create mode 100644 src/Symfony/Bundle/DoctrineBundle/Tests/Command/DoctrineCommandTest.php diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/ConvertDoctrine1SchemaDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/ConvertDoctrine1SchemaDoctrineCommand.php deleted file mode 100644 index 0e4791b40a..0000000000 --- a/src/Symfony/Bundle/DoctrineBundle/Command/ConvertDoctrine1SchemaDoctrineCommand.php +++ /dev/null @@ -1,105 +0,0 @@ - - * - * 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 - * @author Jonathan H. Wage - */ -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(<<doctrine:mapping:convert-d1-schema command converts a Doctrine 1 schema to Doctrine 2 mapping files: - - ./app/console doctrine:mapping:convert-d1-schema /path/to/doctrine1schema "BundleMyBundle" xml - -Each Doctrine 1 model will have its own XML mapping file located in Bundle/MyBundle/config/doctrine/metadata. -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 "%s"', $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 %s', $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'); - } - } -} diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/CreateDatabaseDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/CreateDatabaseDoctrineCommand.php index ba0b608e38..6c89c51f81 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/CreateDatabaseDoctrineCommand.php +++ b/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('Could not find a connection named %s', $input->getOption('connection'))); - } else { - throw new \InvalidArgumentException(sprintf('Could not find any configured connections', $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']; diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php index 9620bb0c88..2e960980fb 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php +++ b/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 */ 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('Could not find a connection named %s', $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() diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/DropDatabaseDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/DropDatabaseDoctrineCommand.php index 32e4e62683..2458bd46ee 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/DropDatabaseDoctrineCommand.php +++ b/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(<<doctrine:database:drop command drops the default connections database: ./app/console doctrine:database:drop +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: ./app/console doctrine:database:drop --connection=default + +Be careful: All data in a given database will be lost when executing this command. 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('Could not find a connection named %s', $input->getOption('connection'))); - } else { - throw new \InvalidArgumentException(sprintf('Could not find any configured connections', $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('Dropped database for connection named %s', $name)); - } catch (\Exception $e) { - $output->writeln(sprintf('Could not drop database for connection named %s', $name)); - $output->writeln(sprintf('%s', $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('Dropped database for connection named %s', $name)); + } catch (\Exception $e) { + $output->writeln(sprintf('Could not drop database for connection named %s', $name)); + $output->writeln(sprintf('%s', $e->getMessage())); + } + } else { + $output->writeln(sprintf('Would drop the database named %.', $name)); + $output->writeln(sprintf('All data will be lost!', $name)); } } } \ No newline at end of file diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php index 85fb8ecb0f..c46dcec497 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php +++ b/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(<<doctrine:generate:entities command generates entity classes and method stubs from your mapping information: - ./app/console doctrine:generate:entities +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: - - ./app/console doctrine:generate:entities --bundle="Bundle/MyCustomBundle" + ./app/console doctrine:generate:entities --bundle="MyCustomBundle" Alternatively, you can limit generation to a single entity within a bundle: - ./app/console doctrine:generate:entities --bundle="Bundle/MyCustomBundle" --entity="User" + ./app/console doctrine:generate:entities --bundle="MyCustomBundle" --entity="User" + +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 "%s"', $class)); foreach ($metadatas as $metadata) { - if ($filterEntity && strpos($metadata->name, $filterEntity) !== 0) { + if ($filterEntity && $metadata->reflClass->getShortName() == $filterEntity) { continue; } $output->writeln(sprintf(' > generating %s', $metadata->name)); diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/GenerateProxiesDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/GenerateProxiesDoctrineCommand.php index 626e622f37..ce464f2bbb 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/GenerateProxiesDoctrineCommand.php +++ b/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(<<doctrine:generate:proxies command generates proxy classes for your entities: +The doctrine:generate:proxies command generates proxy classes for your default entity manager: ./app/console doctrine:generate:proxies + +You can specify the entity manager you want to generate the proxies for: + + ./app/console doctrine:generate:proxies --em=name EOT ); } diff --git a/src/Symfony/Bundle/DoctrineBundle/Tests/Command/DoctrineCommandTest.php b/src/Symfony/Bundle/DoctrineBundle/Tests/Command/DoctrineCommandTest.php new file mode 100644 index 0000000000..5f6c07bc25 --- /dev/null +++ b/src/Symfony/Bundle/DoctrineBundle/Tests/Command/DoctrineCommandTest.php @@ -0,0 +1,56 @@ + + * + * 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; + } +} \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/Command.php b/src/Symfony/Bundle/FrameworkBundle/Command/Command.php index e71f9170c7..399fffc0ee 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/Command.php +++ b/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)