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

This commit is contained in:
Benjamin Eberlei 2011-01-27 00:28:53 +01:00 committed by Fabien Potencier
parent 394a60b4be
commit bdbfb44a96
8 changed files with 126 additions and 225 deletions

View File

@ -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');
}
}
}

View File

@ -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'];

View File

@ -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()

View File

@ -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));
}
}
}

View File

@ -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));

View File

@ -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
);
}

View File

@ -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;
}
}

View File

@ -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)