1
0
mirror of synced 2025-02-02 21:41:45 +03:00

Merge pull request #6655 from OskarStark/symfony-style

Use SymfonyStyle for command output
This commit is contained in:
Luís Cobucci 2017-11-24 01:52:00 +01:00 committed by GitHub
commit b47a39be64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 868 additions and 836 deletions

View File

@ -19,13 +19,14 @@
namespace Doctrine\ORM\Tools\Console\Command\ClearCache; namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Doctrine\ORM\Cache;
use Doctrine\ORM\Cache\Region\DefaultRegion;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Cache\Region\DefaultRegion; use Symfony\Component\Console\Style\SymfonyStyle;
use Doctrine\ORM\Cache;
/** /**
* Command to clear a collection cache region. * Command to clear a collection cache region.
@ -40,17 +41,14 @@ class CollectionRegionCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:clear-cache:region:collection')
->setName('orm:clear-cache:region:collection') ->setDescription('Clear a second-level cache collection region')
->setDescription('Clear a second-level cache collection region.') ->addArgument('owner-class', InputArgument::OPTIONAL, 'The owner entity name.')
->addArgument('owner-class', InputArgument::OPTIONAL, 'The owner entity name.') ->addArgument('association', InputArgument::OPTIONAL, 'The association collection name.')
->addArgument('association', InputArgument::OPTIONAL, 'The association collection name.') ->addArgument('owner-id', InputArgument::OPTIONAL, 'The owner identifier.')
->addArgument('owner-id', InputArgument::OPTIONAL, 'The owner identifier.') ->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.')
->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.') ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.')
->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.'); ->setHelp(<<<EOT
$this->setHelp(<<<EOT
The <info>%command.name%</info> command is meant to clear a second-level cache collection regions for an associated Entity Manager. The <info>%command.name%</info> command is meant to clear a second-level cache collection regions for an associated Entity Manager.
It is possible to delete/invalidate all collection region, a specific collection region or flushes the cache provider. It is possible to delete/invalidate all collection region, a specific collection region or flushes the cache provider.
@ -74,7 +72,7 @@ Alternatively, if you want to flush the configured cache provider for an collect
Finally, be aware that if <info>--flush</info> option is passed, Finally, be aware that if <info>--flush</info> option is passed,
not all cache providers are able to flush entries, because of a limitation of its execution nature. not all cache providers are able to flush entries, because of a limitation of its execution nature.
EOT EOT
); );
} }
/** /**
@ -82,6 +80,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$ownerClass = $input->getArgument('owner-class'); $ownerClass = $input->getArgument('owner-class');
$assoc = $input->getArgument('association'); $assoc = $input->getArgument('association');
@ -92,7 +92,7 @@ EOT
throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.'); throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.');
} }
if ( (! $ownerClass || ! $assoc) && ! $input->getOption('all')) { if (( ! $ownerClass || ! $assoc) && ! $input->getOption('all')) {
throw new \InvalidArgumentException('Missing arguments "--owner-class" "--association"'); throw new \InvalidArgumentException('Missing arguments "--owner-class" "--association"');
} }
@ -108,13 +108,19 @@ EOT
$collectionRegion->getCache()->flushAll(); $collectionRegion->getCache()->flushAll();
$output->writeln(sprintf('Flushing cache provider configured for <info>"%s#%s"</info>', $ownerClass, $assoc)); $ui->comment(
sprintf(
'Flushing cache provider configured for <info>"%s#%s"</info>',
$ownerClass,
$assoc
)
);
return; return;
} }
if ($input->getOption('all')) { if ($input->getOption('all')) {
$output->writeln('Clearing <info>all</info> second-level cache collection regions'); $ui->comment('Clearing <info>all</info> second-level cache collection regions');
$cache->evictEntityRegions(); $cache->evictEntityRegions();
@ -122,13 +128,20 @@ EOT
} }
if ($ownerId) { if ($ownerId) {
$output->writeln(sprintf('Clearing second-level cache entry for collection <info>"%s#%s"</info> owner entity identified by <info>"%s"</info>', $ownerClass, $assoc, $ownerId)); $ui->comment(
sprintf(
'Clearing second-level cache entry for collection <info>"%s#%s"</info> owner entity identified by <info>"%s"</info>',
$ownerClass,
$assoc,
$ownerId
)
);
$cache->evictCollection($ownerClass, $assoc, $ownerId); $cache->evictCollection($ownerClass, $assoc, $ownerId);
return; return;
} }
$output->writeln(sprintf('Clearing second-level cache for collection <info>"%s#%s"</info>', $ownerClass, $assoc)); $ui->comment(sprintf('Clearing second-level cache for collection <info>"%s#%s"</info>', $ownerClass, $assoc));
$cache->evictCollectionRegion($ownerClass, $assoc); $cache->evictCollectionRegion($ownerClass, $assoc);
} }
} }

View File

@ -19,13 +19,14 @@
namespace Doctrine\ORM\Tools\Console\Command\ClearCache; namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Doctrine\ORM\Cache;
use Doctrine\ORM\Cache\Region\DefaultRegion;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Cache\Region\DefaultRegion; use Symfony\Component\Console\Style\SymfonyStyle;
use Doctrine\ORM\Cache;
/** /**
* Command to clear a entity cache region. * Command to clear a entity cache region.
@ -40,16 +41,13 @@ class EntityRegionCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:clear-cache:region:entity')
->setName('orm:clear-cache:region:entity') ->setDescription('Clear a second-level cache entity region')
->setDescription('Clear a second-level cache entity region.') ->addArgument('entity-class', InputArgument::OPTIONAL, 'The entity name.')
->addArgument('entity-class', InputArgument::OPTIONAL, 'The entity name.') ->addArgument('entity-id', InputArgument::OPTIONAL, 'The entity identifier.')
->addArgument('entity-id', InputArgument::OPTIONAL, 'The entity identifier.') ->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.')
->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.') ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.')
->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.'); ->setHelp(<<<EOT
$this->setHelp(<<<EOT
The <info>%command.name%</info> command is meant to clear a second-level cache entity region for an associated Entity Manager. The <info>%command.name%</info> command is meant to clear a second-level cache entity region for an associated Entity Manager.
It is possible to delete/invalidate all entity region, a specific entity region or flushes the cache provider. It is possible to delete/invalidate all entity region, a specific entity region or flushes the cache provider.
@ -73,7 +71,7 @@ Alternatively, if you want to flush the configured cache provider for an entity
Finally, be aware that if <info>--flush</info> option is passed, Finally, be aware that if <info>--flush</info> option is passed,
not all cache providers are able to flush entries, because of a limitation of its execution nature. not all cache providers are able to flush entries, because of a limitation of its execution nature.
EOT EOT
); );
} }
/** /**
@ -81,6 +79,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$entityClass = $input->getArgument('entity-class'); $entityClass = $input->getArgument('entity-class');
$entityId = $input->getArgument('entity-id'); $entityId = $input->getArgument('entity-id');
@ -106,13 +106,13 @@ EOT
$entityRegion->getCache()->flushAll(); $entityRegion->getCache()->flushAll();
$output->writeln(sprintf('Flushing cache provider configured for entity named <info>"%s"</info>', $entityClass)); $ui->comment(sprintf('Flushing cache provider configured for entity named <info>"%s"</info>', $entityClass));
return; return;
} }
if ($input->getOption('all')) { if ($input->getOption('all')) {
$output->writeln('Clearing <info>all</info> second-level cache entity regions'); $ui->comment('Clearing <info>all</info> second-level cache entity regions');
$cache->evictEntityRegions(); $cache->evictEntityRegions();
@ -120,13 +120,19 @@ EOT
} }
if ($entityId) { if ($entityId) {
$output->writeln(sprintf('Clearing second-level cache entry for entity <info>"%s"</info> identified by <info>"%s"</info>', $entityClass, $entityId)); $ui->comment(
sprintf(
'Clearing second-level cache entry for entity <info>"%s"</info> identified by <info>"%s"</info>',
$entityClass,
$entityId
)
);
$cache->evictEntity($entityClass, $entityId); $cache->evictEntity($entityClass, $entityId);
return; return;
} }
$output->writeln(sprintf('Clearing second-level cache for entity <info>"%s"</info>', $entityClass)); $ui->comment(sprintf('Clearing second-level cache for entity <info>"%s"</info>', $entityClass));
$cache->evictEntityRegion($entityClass); $cache->evictEntityRegion($entityClass);
} }
} }

View File

@ -19,12 +19,13 @@
namespace Doctrine\ORM\Tools\Console\Command\ClearCache; namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\Common\Cache\ApcCache; use Doctrine\Common\Cache\ApcCache;
use Doctrine\Common\Cache\XcacheCache; use Doctrine\Common\Cache\XcacheCache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to clear the metadata cache of the various cache drivers. * Command to clear the metadata cache of the various cache drivers.
@ -43,19 +44,10 @@ class MetadataCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:clear-cache:metadata')
->setName('orm:clear-cache:metadata') ->setDescription('Clear all metadata cache of the various cache drivers')
->setDescription('Clear all metadata cache of the various cache drivers.') ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, cache entries will be flushed instead of deleted/invalidated.')
->setDefinition( ->setHelp(<<<EOT
[
new InputOption(
'flush', null, InputOption::VALUE_NONE,
'If defined, cache entries will be flushed instead of deleted/invalidated.'
)
]
);
$this->setHelp(<<<EOT
The <info>%command.name%</info> command is meant to clear the metadata cache of associated Entity Manager. The <info>%command.name%</info> command is meant to clear the metadata cache of associated Entity Manager.
It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider
instance completely. instance completely.
@ -72,7 +64,7 @@ Alternatively, if you want to flush the cache provider using this command:
Finally, be aware that if <info>--flush</info> option is passed, not all cache providers are able to flush entries, Finally, be aware that if <info>--flush</info> option is passed, not all cache providers are able to flush entries,
because of a limitation of its execution nature. because of a limitation of its execution nature.
EOT EOT
); );
} }
/** /**
@ -80,6 +72,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$cacheDriver = $em->getConfiguration()->getMetadataCacheImpl(); $cacheDriver = $em->getConfiguration()->getMetadataCacheImpl();
@ -95,8 +89,7 @@ EOT
throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
} }
$ui->comment('Clearing <info>all</info> Metadata cache entries');
$output->writeln('Clearing ALL Metadata cache entries');
$result = $cacheDriver->deleteAll(); $result = $cacheDriver->deleteAll();
$message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.'; $message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.';
@ -106,6 +99,14 @@ EOT
$message = ($result) ? 'Successfully flushed cache entries.' : $message; $message = ($result) ? 'Successfully flushed cache entries.' : $message;
} }
$output->writeln($message); if ( ! $result) {
$ui->error($message);
return 1;
}
$ui->success($message);
return 0;
} }
} }

View File

@ -19,12 +19,13 @@
namespace Doctrine\ORM\Tools\Console\Command\ClearCache; namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\Common\Cache\ApcCache; use Doctrine\Common\Cache\ApcCache;
use Doctrine\Common\Cache\XcacheCache; use Doctrine\Common\Cache\XcacheCache;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to clear the query cache of the various cache drivers. * Command to clear the query cache of the various cache drivers.
@ -43,19 +44,10 @@ class QueryCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:clear-cache:query')
->setName('orm:clear-cache:query') ->setDescription('Clear all query cache of the various cache drivers')
->setDescription('Clear all query cache of the various cache drivers.') ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, cache entries will be flushed instead of deleted/invalidated.')
->setDefinition( ->setHelp(<<<EOT
[
new InputOption(
'flush', null, InputOption::VALUE_NONE,
'If defined, cache entries will be flushed instead of deleted/invalidated.'
)
]
);
$this->setHelp(<<<EOT
The <info>%command.name%</info> command is meant to clear the query cache of associated Entity Manager. The <info>%command.name%</info> command is meant to clear the query cache of associated Entity Manager.
It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider
instance completely. instance completely.
@ -72,7 +64,7 @@ Alternatively, if you want to flush the cache provider using this command:
Finally, be aware that if <info>--flush</info> option is passed, not all cache providers are able to flush entries, Finally, be aware that if <info>--flush</info> option is passed, not all cache providers are able to flush entries,
because of a limitation of its execution nature. because of a limitation of its execution nature.
EOT EOT
); );
} }
/** /**
@ -80,6 +72,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$cacheDriver = $em->getConfiguration()->getQueryCacheImpl(); $cacheDriver = $em->getConfiguration()->getQueryCacheImpl();
@ -94,7 +88,7 @@ EOT
throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
} }
$output->write('Clearing ALL Query cache entries' . PHP_EOL); $ui->comment('Clearing <info>all</info> Query cache entries');
$result = $cacheDriver->deleteAll(); $result = $cacheDriver->deleteAll();
$message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.'; $message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.';
@ -104,6 +98,14 @@ EOT
$message = ($result) ? 'Successfully flushed cache entries.' : $message; $message = ($result) ? 'Successfully flushed cache entries.' : $message;
} }
$output->write($message . PHP_EOL); if ( ! $result) {
$ui->error($message);
return 1;
}
$ui->success($message);
return 0;
} }
} }

View File

@ -19,13 +19,14 @@
namespace Doctrine\ORM\Tools\Console\Command\ClearCache; namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Doctrine\ORM\Cache;
use Doctrine\ORM\Cache\Region\DefaultRegion;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Cache\Region\DefaultRegion; use Symfony\Component\Console\Style\SymfonyStyle;
use Doctrine\ORM\Cache;
/** /**
* Command to clear a query cache region. * Command to clear a query cache region.
@ -40,15 +41,12 @@ class QueryRegionCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:clear-cache:region:query')
->setName('orm:clear-cache:region:query') ->setDescription('Clear a second-level cache query region')
->setDescription('Clear a second-level cache query region.') ->addArgument('region-name', InputArgument::OPTIONAL, 'The query region to clear.')
->addArgument('region-name', InputArgument::OPTIONAL, 'The query region to clear.') ->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all query regions will be deleted/invalidated.')
->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all query regions will be deleted/invalidated.') ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.')
->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.'); ->setHelp(<<<EOT
$this->setHelp(<<<EOT
The <info>%command.name%</info> command is meant to clear a second-level cache query region for an associated Entity Manager. The <info>%command.name%</info> command is meant to clear a second-level cache query region for an associated Entity Manager.
It is possible to delete/invalidate all query region, a specific query region or flushes the cache provider. It is possible to delete/invalidate all query region, a specific query region or flushes the cache provider.
@ -72,7 +70,7 @@ Alternatively, if you want to flush the configured cache provider use this comma
Finally, be aware that if <info>--flush</info> option is passed, Finally, be aware that if <info>--flush</info> option is passed,
not all cache providers are able to flush entries, because of a limitation of its execution nature. not all cache providers are able to flush entries, because of a limitation of its execution nature.
EOT EOT
); );
} }
/** /**
@ -80,6 +78,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$name = $input->getArgument('region-name'); $name = $input->getArgument('region-name');
$cache = $em->getCache(); $cache = $em->getCache();
@ -105,20 +105,25 @@ EOT
$queryRegion->getCache()->flushAll(); $queryRegion->getCache()->flushAll();
$output->writeln(sprintf('Flushing cache provider configured for second-level cache query region named <info>"%s"</info>', $name)); $ui->comment(
sprintf(
'Flushing cache provider configured for second-level cache query region named <info>"%s"</info>',
$name
)
);
return; return;
} }
if ($input->getOption('all')) { if ($input->getOption('all')) {
$output->writeln('Clearing <info>all</info> second-level cache query regions'); $ui->comment('Clearing <info>all</info> second-level cache query regions');
$cache->evictQueryRegions(); $cache->evictQueryRegions();
return; return;
} }
$output->writeln(sprintf('Clearing second-level cache query region named <info>"%s"</info>', $name)); $ui->comment(sprintf('Clearing second-level cache query region named <info>"%s"</info>', $name));
$cache->evictQueryRegion($name); $cache->evictQueryRegion($name);
} }
} }

View File

@ -19,12 +19,13 @@
namespace Doctrine\ORM\Tools\Console\Command\ClearCache; namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Doctrine\Common\Cache\ApcCache;
use Doctrine\Common\Cache\XcacheCache;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\Common\Cache\ApcCache; use Symfony\Component\Console\Style\SymfonyStyle;
use Doctrine\Common\Cache\XcacheCache;
/** /**
* Command to clear the result cache of the various cache drivers. * Command to clear the result cache of the various cache drivers.
@ -43,19 +44,10 @@ class ResultCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:clear-cache:result')
->setName('orm:clear-cache:result') ->setDescription('Clear all result cache of the various cache drivers')
->setDescription('Clear all result cache of the various cache drivers.') ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, cache entries will be flushed instead of deleted/invalidated.')
->setDefinition( ->setHelp(<<<EOT
[
new InputOption(
'flush', null, InputOption::VALUE_NONE,
'If defined, cache entries will be flushed instead of deleted/invalidated.'
)
]
);
$this->setHelp(<<<EOT
The <info>%command.name%</info> command is meant to clear the result cache of associated Entity Manager. The <info>%command.name%</info> command is meant to clear the result cache of associated Entity Manager.
It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider
instance completely. instance completely.
@ -72,7 +64,7 @@ Alternatively, if you want to flush the cache provider using this command:
Finally, be aware that if <info>--flush</info> option is passed, not all cache providers are able to flush entries, Finally, be aware that if <info>--flush</info> option is passed, not all cache providers are able to flush entries,
because of a limitation of its execution nature. because of a limitation of its execution nature.
EOT EOT
); );
} }
/** /**
@ -80,6 +72,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$cacheDriver = $em->getConfiguration()->getResultCacheImpl(); $cacheDriver = $em->getConfiguration()->getResultCacheImpl();
@ -95,7 +89,7 @@ EOT
throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
} }
$output->writeln('Clearing ALL Result cache entries'); $ui->comment('Clearing <info>all</info> Result cache entries');
$result = $cacheDriver->deleteAll(); $result = $cacheDriver->deleteAll();
$message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.'; $message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.';
@ -105,6 +99,14 @@ EOT
$message = ($result) ? 'Successfully flushed cache entries.' : $message; $message = ($result) ? 'Successfully flushed cache entries.' : $message;
} }
$output->writeln($message); if ( ! $result) {
$ui->error($message);
return 1;
}
$ui->success($message);
return 0;
} }
} }

View File

@ -19,14 +19,14 @@
namespace Doctrine\ORM\Tools\Console\Command; namespace Doctrine\ORM\Tools\Console\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
use Doctrine\ORM\Tools\ConvertDoctrine1Schema; use Doctrine\ORM\Tools\ConvertDoctrine1Schema;
use Doctrine\ORM\Tools\EntityGenerator; use Doctrine\ORM\Tools\EntityGenerator;
use Symfony\Component\Console\Output\OutputInterface; use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/** /**
* Command to convert a Doctrine 1 schema to a Doctrine 2 mapping file. * Command to convert a Doctrine 1 schema to a Doctrine 2 mapping file.
@ -99,41 +99,16 @@ class ConvertDoctrine1SchemaCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:convert-d1-schema')
->setName('orm:convert-d1-schema') ->setAliases(['orm:convert:d1-schema'])
->setAliases(['orm:convert:d1-schema']) ->setDescription('Converts Doctrine 1.x schema into a Doctrine 2.x schema')
->setDescription('Converts Doctrine 1.X schema into a Doctrine 2.X schema.') ->addArgument('from-path', InputArgument::REQUIRED, 'The path of Doctrine 1.X schema information.')
->setDefinition( ->addArgument('to-type', InputArgument::REQUIRED, 'The destination Doctrine 2.X mapping type.')
[ ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your Doctrine 2.X mapping information.')
new InputArgument( ->addOption('from', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Optional paths of Doctrine 1.X schema information.', [])
'from-path', InputArgument::REQUIRED, 'The path of Doctrine 1.X schema information.' ->addOption('extend', null, InputOption::VALUE_OPTIONAL, 'Defines a base class to be extended by generated entity classes.')
), ->addOption('num-spaces', null, InputOption::VALUE_OPTIONAL, 'Defines the number of indentation spaces', 4)
new InputArgument( ->setHelp('Converts Doctrine 1.x schema into a Doctrine 2.x schema.');
'to-type', InputArgument::REQUIRED, 'The destination Doctrine 2.X mapping type.'
),
new InputArgument(
'dest-path', InputArgument::REQUIRED,
'The path to generate your Doctrine 2.X mapping information.'
),
new InputOption(
'from', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Optional paths of Doctrine 1.X schema information.',
[]
),
new InputOption(
'extend', null, InputOption::VALUE_OPTIONAL,
'Defines a base class to be extended by generated entity classes.'
),
new InputOption(
'num-spaces', null, InputOption::VALUE_OPTIONAL,
'Defines the number of indentation spaces', 4
)
]
)
->setHelp(<<<EOT
Converts Doctrine 1.X schema into a Doctrine 2.X schema.
EOT
);
} }
/** /**

View File

@ -19,16 +19,17 @@
namespace Doctrine\ORM\Tools\Console\Command; namespace Doctrine\ORM\Tools\Console\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Doctrine\ORM\Tools\Console\MetadataFilter;
use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
use Doctrine\ORM\Tools\EntityGenerator;
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
use Doctrine\ORM\Mapping\Driver\DatabaseDriver; use Doctrine\ORM\Mapping\Driver\DatabaseDriver;
use Symfony\Component\Console\Output\OutputInterface; use Doctrine\ORM\Tools\Console\MetadataFilter;
use Symfony\Component\Console\Input\InputInterface; use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
use Doctrine\ORM\Tools\EntityGenerator;
use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to convert your mapping information between the various formats. * Command to convert your mapping information between the various formats.
@ -47,45 +48,18 @@ class ConvertMappingCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:convert-mapping')
->setName('orm:convert-mapping') ->setAliases(['orm:convert:mapping'])
->setAliases(['orm:convert:mapping']) ->setDescription('Convert mapping information between supported formats')
->setDescription('Convert mapping information between supported formats.') ->addArgument('to-type', InputArgument::REQUIRED, 'The mapping type to be converted.')
->setDefinition( ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your entities classes.')
[ ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.')
new InputOption( ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force to overwrite existing mapping files.')
'filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, ->addOption('from-database', null, null, 'Whether or not to convert mapping information from existing database.')
'A string pattern used to match entities that should be processed.' ->addOption('extend', null, InputOption::VALUE_OPTIONAL, 'Defines a base class to be extended by generated entity classes.')
), ->addOption('num-spaces', null, InputOption::VALUE_OPTIONAL, 'Defines the number of indentation spaces', 4)
new InputArgument( ->addOption('namespace', null, InputOption::VALUE_OPTIONAL, 'Defines a namespace for the generated entity classes, if converted from database.')
'to-type', InputArgument::REQUIRED, 'The mapping type to be converted.' ->setHelp(<<<EOT
),
new InputArgument(
'dest-path', InputArgument::REQUIRED,
'The path to generate your entities classes.'
),
new InputOption(
'force', 'f', InputOption::VALUE_NONE,
'Force to overwrite existing mapping files.'
),
new InputOption(
'from-database', null, null, 'Whether or not to convert mapping information from existing database.'
),
new InputOption(
'extend', null, InputOption::VALUE_OPTIONAL,
'Defines a base class to be extended by generated entity classes.'
),
new InputOption(
'num-spaces', null, InputOption::VALUE_OPTIONAL,
'Defines the number of indentation spaces', 4
),
new InputOption(
'namespace', null, InputOption::VALUE_OPTIONAL,
'Defines a namespace for the generated entity classes, if converted from database.'
),
]
)
->setHelp(<<<EOT
Convert mapping information between supported formats. Convert mapping information between supported formats.
This is an execute <info>one-time</info> command. It should not be necessary for This is an execute <info>one-time</info> command. It should not be necessary for
@ -108,7 +82,7 @@ on a global level:
\$config->setFilterSchemaAssetsExpression(\$regexp); \$config->setFilterSchemaAssetsExpression(\$regexp);
EOT EOT
); );
} }
/** /**
@ -116,6 +90,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
if ($input->getOption('from-database') === true) { if ($input->getOption('from-database') === true) {
@ -171,20 +147,26 @@ EOT
} }
} }
if (count($metadata)) { if (empty($metadata)) {
foreach ($metadata as $class) { $ui->success('No Metadata Classes to process.');
$output->writeln(sprintf('Processing entity "<info>%s</info>"', $class->name)); return;
}
$exporter->setMetadata($metadata);
$exporter->export();
$output->writeln(PHP_EOL . sprintf(
'Exporting "<info>%s</info>" mapping information to "<info>%s</info>"', $toType, $destPath
));
} else {
$output->writeln('No Metadata Classes to process.');
} }
foreach ($metadata as $class) {
$ui->text(sprintf('Processing entity "<info>%s</info>"', $class->name));
}
$exporter->setMetadata($metadata);
$exporter->export();
$ui->newLine();
$ui->text(
sprintf(
'Exporting "<info>%s</info>" mapping information to "<info>%s</info>"',
$toType,
$destPath
)
);
} }
/** /**

View File

@ -20,9 +20,10 @@
namespace Doctrine\ORM\Tools\Console\Command; namespace Doctrine\ORM\Tools\Console\Command;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Throwable; use Throwable;
/** /**
@ -43,21 +44,10 @@ class EnsureProductionSettingsCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:ensure-production-settings')
->setName('orm:ensure-production-settings') ->setDescription('Verify that Doctrine is properly configured for a production environment')
->setDescription('Verify that Doctrine is properly configured for a production environment.') ->addOption('complete', null, InputOption::VALUE_NONE, 'Flag to also inspect database connection existence.')
->setDefinition( ->setHelp('Verify that Doctrine is properly configured for a production environment.');
[
new InputOption(
'complete', null, InputOption::VALUE_NONE,
'Flag to also inspect database connection existence.'
)
]
)
->setHelp(<<<EOT
Verify that Doctrine is properly configured for a production environment.
EOT
);
} }
/** /**
@ -65,6 +55,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
try { try {
@ -74,11 +66,13 @@ EOT
$em->getConnection()->connect(); $em->getConnection()->connect();
} }
} catch (Throwable $e) { } catch (Throwable $e) {
$output->writeln('<error>' . $e->getMessage() . '</error>'); $ui->error($e->getMessage());
return 1; return 1;
} }
$output->writeln('<info>Environment is correctly configured for production.</info>'); $ui->success('Environment is correctly configured for production.');
return 0;
} }
} }

View File

@ -19,14 +19,15 @@
namespace Doctrine\ORM\Tools\Console\Command; namespace Doctrine\ORM\Tools\Console\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Doctrine\ORM\Tools\Console\MetadataFilter; use Doctrine\ORM\Tools\Console\MetadataFilter;
use Doctrine\ORM\Tools\EntityGenerator;
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory; use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
use Symfony\Component\Console\Output\OutputInterface; use Doctrine\ORM\Tools\EntityGenerator;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to generate entity classes and method stubs from your mapping information. * Command to generate entity classes and method stubs from your mapping information.
@ -45,50 +46,19 @@ class GenerateEntitiesCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:generate-entities')
->setName('orm:generate-entities') ->setAliases(['orm:generate:entities'])
->setAliases(['orm:generate:entities']) ->setDescription('Generate entity classes and method stubs from your mapping information')
->setDescription('Generate entity classes and method stubs from your mapping information.') ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your entity classes.')
->setDefinition( ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.')
[ ->addOption('generate-annotations', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should generate annotation metadata on entities.', false)
new InputOption( ->addOption('generate-methods', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should generate stub methods on entities.', true)
'filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, ->addOption('regenerate-entities', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should regenerate entity if it exists.', false)
'A string pattern used to match entities that should be processed.' ->addOption('update-entities', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should only update entity if it exists.', true)
), ->addOption('extend', null, InputOption::VALUE_REQUIRED, 'Defines a base class to be extended by generated entity classes.')
new InputArgument( ->addOption('num-spaces', null, InputOption::VALUE_REQUIRED, 'Defines the number of indentation spaces', 4)
'dest-path', InputArgument::REQUIRED, 'The path to generate your entity classes.' ->addOption('no-backup', null, InputOption::VALUE_NONE, 'Flag to define if generator should avoid backuping existing entity file if it exists.')
), ->setHelp(<<<EOT
new InputOption(
'generate-annotations', null, InputOption::VALUE_OPTIONAL,
'Flag to define if generator should generate annotation metadata on entities.', false
),
new InputOption(
'generate-methods', null, InputOption::VALUE_OPTIONAL,
'Flag to define if generator should generate stub methods on entities.', true
),
new InputOption(
'regenerate-entities', null, InputOption::VALUE_OPTIONAL,
'Flag to define if generator should regenerate entity if it exists.', false
),
new InputOption(
'update-entities', null, InputOption::VALUE_OPTIONAL,
'Flag to define if generator should only update entity if it exists.', true
),
new InputOption(
'extend', null, InputOption::VALUE_REQUIRED,
'Defines a base class to be extended by generated entity classes.'
),
new InputOption(
'num-spaces', null, InputOption::VALUE_REQUIRED,
'Defines the number of indentation spaces', 4
),
new InputOption(
'no-backup', null, InputOption::VALUE_NONE,
'Flag to define if generator should avoid backuping existing entity file if it exists.'
)
]
)
->setHelp(<<<EOT
Generate entity classes and method stubs from your mapping information. Generate entity classes and method stubs from your mapping information.
If you use the <comment>--update-entities</comment> or <comment>--regenerate-entities</comment> flags your existing If you use the <comment>--update-entities</comment> or <comment>--regenerate-entities</comment> flags your existing
@ -108,7 +78,7 @@ child classes for you correctly, because it doesn't know which
class is supposed to extend which. You have to adjust the entity class is supposed to extend which. You have to adjust the entity
code manually for inheritance to work! code manually for inheritance to work!
EOT EOT
); );
} }
/** /**
@ -116,6 +86,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$cmf = new DisconnectedClassMetadataFactory(); $cmf = new DisconnectedClassMetadataFactory();
@ -138,34 +110,33 @@ EOT
); );
} }
if (count($metadatas)) { if (empty($metadatas)) {
// Create EntityGenerator $ui->success('No Metadata Classes to process.');
$entityGenerator = new EntityGenerator(); return;
$entityGenerator->setGenerateAnnotations($input->getOption('generate-annotations'));
$entityGenerator->setGenerateStubMethods($input->getOption('generate-methods'));
$entityGenerator->setRegenerateEntityIfExists($input->getOption('regenerate-entities'));
$entityGenerator->setUpdateEntityIfExists($input->getOption('update-entities'));
$entityGenerator->setNumSpaces($input->getOption('num-spaces'));
$entityGenerator->setBackupExisting(!$input->getOption('no-backup'));
if (($extend = $input->getOption('extend')) !== null) {
$entityGenerator->setClassToExtend($extend);
}
foreach ($metadatas as $metadata) {
$output->writeln(
sprintf('Processing entity "<info>%s</info>"', $metadata->name)
);
}
// Generating Entities
$entityGenerator->generate($metadatas, $destPath);
// Outputting information message
$output->writeln(PHP_EOL . sprintf('Entity classes generated to "<info>%s</INFO>"', $destPath));
} else {
$output->writeln('No Metadata Classes to process.');
} }
$entityGenerator = new EntityGenerator();
$entityGenerator->setGenerateAnnotations($input->getOption('generate-annotations'));
$entityGenerator->setGenerateStubMethods($input->getOption('generate-methods'));
$entityGenerator->setRegenerateEntityIfExists($input->getOption('regenerate-entities'));
$entityGenerator->setUpdateEntityIfExists($input->getOption('update-entities'));
$entityGenerator->setNumSpaces($input->getOption('num-spaces'));
$entityGenerator->setBackupExisting(!$input->getOption('no-backup'));
if (($extend = $input->getOption('extend')) !== null) {
$entityGenerator->setClassToExtend($extend);
}
foreach ($metadatas as $metadata) {
$ui->text(sprintf('Processing entity "<info>%s</info>"', $metadata->name));
}
// Generating Entities
$entityGenerator->generate($metadatas, $destPath);
// Outputting information message
$ui->newLine();
$ui->success(sprintf('Entity classes generated to "%s"', $destPath));
} }
} }

View File

@ -19,12 +19,14 @@
namespace Doctrine\ORM\Tools\Console\Command; namespace Doctrine\ORM\Tools\Console\Command;
use Symfony\Component\Console\Input\InputArgument; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Input\InputOption;
use Doctrine\ORM\Tools\Console\MetadataFilter; use Doctrine\ORM\Tools\Console\MetadataFilter;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to (re)generate the proxy classes used by doctrine. * Command to (re)generate the proxy classes used by doctrine.
@ -43,26 +45,12 @@ class GenerateProxiesCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:generate-proxies')
->setName('orm:generate-proxies') ->setAliases(['orm:generate:proxies'])
->setAliases(['orm:generate:proxies']) ->setDescription('Generates proxy classes for entity classes')
->setDescription('Generates proxy classes for entity classes.') ->addArgument('dest-path', InputArgument::OPTIONAL, 'The path to generate your proxy classes. If none is provided, it will attempt to grab from configuration.')
->setDefinition( ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.')
[ ->setHelp('Generates proxy classes for entity classes.');
new InputOption(
'filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'A string pattern used to match entities that should be processed.'
),
new InputArgument(
'dest-path', InputArgument::OPTIONAL,
'The path to generate your proxy classes. If none is provided, it will attempt to grab from configuration.'
),
]
)
->setHelp(<<<EOT
Generates proxy classes for entity classes.
EOT
);
} }
/** /**
@ -70,6 +58,9 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
/** @var EntityManagerInterface $em */
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$metadatas = $em->getMetadataFactory()->getAllMetadata(); $metadatas = $em->getMetadataFactory()->getAllMetadata();
@ -98,20 +89,20 @@ EOT
); );
} }
if ( count($metadatas)) { if (empty($metadatas)) {
foreach ($metadatas as $metadata) { $ui->success('No Metadata Classes to process.');
$output->writeln( return;
sprintf('Processing entity "<info>%s</info>"', $metadata->name)
);
}
// Generating Proxies
$em->getProxyFactory()->generateProxyClasses($metadatas, $destPath);
// Outputting information message
$output->writeln(PHP_EOL . sprintf('Proxy classes generated to "<info>%s</INFO>"', $destPath));
} else {
$output->writeln('No Metadata Classes to process.');
} }
foreach ($metadatas as $metadata) {
$ui->text(sprintf('Processing entity "<info>%s</info>"', $metadata->name));
}
// Generating Proxies
$em->getProxyFactory()->generateProxyClasses($metadatas, $destPath);
// Outputting information message
$ui->newLine();
$ui->text(sprintf('Proxy classes generated to "<info>%s</INFO>"', $destPath));
} }
} }

View File

@ -19,13 +19,14 @@
namespace Doctrine\ORM\Tools\Console\Command; namespace Doctrine\ORM\Tools\Console\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Doctrine\ORM\Tools\Console\MetadataFilter; use Doctrine\ORM\Tools\Console\MetadataFilter;
use Doctrine\ORM\Tools\EntityRepositoryGenerator; use Doctrine\ORM\Tools\EntityRepositoryGenerator;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to generate repository classes for mapping information. * Command to generate repository classes for mapping information.
@ -44,25 +45,12 @@ class GenerateRepositoriesCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:generate-repositories')
->setName('orm:generate-repositories') ->setAliases(['orm:generate:repositories'])
->setAliases(['orm:generate:repositories']) ->setDescription('Generate repository classes from your mapping information')
->setDescription('Generate repository classes from your mapping information.') ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your repository classes.')
->setDefinition( ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.')
[ ->setHelp('Generate repository classes from your mapping information.');
new InputOption(
'filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'A string pattern used to match entities that should be processed.'
),
new InputArgument(
'dest-path', InputArgument::REQUIRED, 'The path to generate your repository classes.'
)
]
)
->setHelp(<<<EOT
Generate repository classes from your mapping information.
EOT
);
} }
/** /**
@ -70,6 +58,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$metadatas = $em->getMetadataFactory()->getAllMetadata(); $metadatas = $em->getMetadataFactory()->getAllMetadata();
@ -92,32 +82,33 @@ EOT
); );
} }
if (count($metadatas)) { if (empty($metadatas)) {
$numRepositories = 0; $ui->success('No Metadata Classes to process.');
$generator = new EntityRepositoryGenerator(); return;
$generator->setDefaultRepositoryName($repositoryName);
foreach ($metadatas as $metadata) {
if ($metadata->customRepositoryClassName) {
$output->writeln(
sprintf('Processing repository "<info>%s</info>"', $metadata->customRepositoryClassName)
);
$generator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $destPath);
$numRepositories++;
}
}
if ($numRepositories) {
// Outputting information message
$output->writeln(PHP_EOL . sprintf('Repository classes generated to "<info>%s</INFO>"', $destPath));
} else {
$output->writeln('No Repository classes were found to be processed.');
}
} else {
$output->writeln('No Metadata Classes to process.');
} }
$numRepositories = 0;
$generator = new EntityRepositoryGenerator();
$generator->setDefaultRepositoryName($repositoryName);
foreach ($metadatas as $metadata) {
if ($metadata->customRepositoryClassName) {
$ui->text(sprintf('Processing repository "<info>%s</info>"', $metadata->customRepositoryClassName));
$generator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $destPath);
++$numRepositories;
}
}
if ($numRepositories === 0) {
$ui->text('No Repository classes were found to be processed.');
return;
}
// Outputting information message
$ui->newLine();
$ui->text(sprintf('Repository classes generated to "<info>%s</INFO>"', $destPath));
} }
} }

View File

@ -20,9 +20,10 @@
namespace Doctrine\ORM\Tools\Console\Command; namespace Doctrine\ORM\Tools\Console\Command;
use Doctrine\ORM\Mapping\MappingException; use Doctrine\ORM\Mapping\MappingException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Show information about mapped entities. * Show information about mapped entities.
@ -38,15 +39,14 @@ class InfoCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:info')
->setName('orm:info') ->setDescription('Show basic information about all mapped entities')
->setDescription('Show basic information about all mapped entities') ->setHelp(<<<EOT
->setHelp(<<<EOT
The <info>%command.name%</info> shows basic information about which The <info>%command.name%</info> shows basic information about which
entities exist and possibly if their mapping information contains errors or entities exist and possibly if their mapping information contains errors or
not. not.
EOT EOT
); );
} }
/** /**
@ -54,6 +54,8 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
/* @var $entityManager \Doctrine\ORM\EntityManager */ /* @var $entityManager \Doctrine\ORM\EntityManager */
$entityManager = $this->getHelper('em')->getEntityManager(); $entityManager = $this->getHelper('em')->getEntityManager();
@ -61,25 +63,34 @@ EOT
->getMetadataDriverImpl() ->getMetadataDriverImpl()
->getAllClassNames(); ->getAllClassNames();
if (!$entityClassNames) { if ( ! $entityClassNames) {
throw new \Exception( $ui->caution(
'You do not have any mapped Doctrine ORM entities according to the current configuration. '. [
'If you have entities or mapping files you should check your mapping configuration for errors.' 'You do not have any mapped Doctrine ORM entities according to the current configuration.',
'If you have entities or mapping files you should check your mapping configuration for errors.'
]
); );
return 1;
} }
$output->writeln(sprintf("Found <info>%d</info> mapped entities:", count($entityClassNames))); $ui->text(sprintf("Found <info>%d</info> mapped entities:", count($entityClassNames)));
$ui->newLine();
$failure = false; $failure = false;
foreach ($entityClassNames as $entityClassName) { foreach ($entityClassNames as $entityClassName) {
try { try {
$entityManager->getClassMetadata($entityClassName); $entityManager->getClassMetadata($entityClassName);
$output->writeln(sprintf("<info>[OK]</info> %s", $entityClassName)); $ui->text(sprintf("<info>[OK]</info> %s", $entityClassName));
} catch (MappingException $e) { } catch (MappingException $e) {
$output->writeln("<error>[FAIL]</error> ".$entityClassName); $ui->text(
$output->writeln(sprintf("<comment>%s</comment>", $e->getMessage())); [
$output->writeln(''); sprintf("<error>[FAIL]</error> %s", $entityClassName),
sprintf("<comment>%s</comment>", $e->getMessage()),
''
]
);
$failure = true; $failure = true;
} }

View File

@ -22,10 +22,10 @@ namespace Doctrine\ORM\Tools\Console\Command;
use Doctrine\Common\Persistence\Mapping\MappingException; use Doctrine\Common\Persistence\Mapping\MappingException;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Show information about mapped entities. * Show information about mapped entities.
@ -41,11 +41,10 @@ final class MappingDescribeCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:mapping:describe')
->setName('orm:mapping:describe') ->addArgument('entityName', InputArgument::REQUIRED, 'Full or partial name of entity')
->addArgument('entityName', InputArgument::REQUIRED, 'Full or partial name of entity') ->setDescription('Display information about mapped objects')
->setDescription('Display information about mapped objects') ->setHelp(<<<EOT
->setHelp(<<<EOT
The %command.full_name% command describes the metadata for the given full or partial entity class name. The %command.full_name% command describes the metadata for the given full or partial entity class name.
<info>%command.full_name%</info> My\Namespace\Entity\MyEntity <info>%command.full_name%</info> My\Namespace\Entity\MyEntity
@ -54,7 +53,7 @@ Or:
<info>%command.full_name%</info> MyEntity <info>%command.full_name%</info> MyEntity
EOT EOT
); );
} }
/** /**
@ -62,10 +61,12 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
/* @var $entityManager \Doctrine\ORM\EntityManagerInterface */ /* @var $entityManager \Doctrine\ORM\EntityManagerInterface */
$entityManager = $this->getHelper('em')->getEntityManager(); $entityManager = $this->getHelper('em')->getEntityManager();
$this->displayEntity($input->getArgument('entityName'), $entityManager, $output); $this->displayEntity($input->getArgument('entityName'), $entityManager, $ui);
return 0; return 0;
} }
@ -75,18 +76,14 @@ EOT
* *
* @param string $entityName Full or partial entity class name * @param string $entityName Full or partial entity class name
* @param EntityManagerInterface $entityManager * @param EntityManagerInterface $entityManager
* @param OutputInterface $output * @param SymfonyStyle $ui
*/ */
private function displayEntity($entityName, EntityManagerInterface $entityManager, OutputInterface $output) private function displayEntity($entityName, EntityManagerInterface $entityManager, SymfonyStyle $ui)
{ {
$table = new Table($output);
$table->setHeaders(['Field', 'Value']);
$metadata = $this->getClassMetadata($entityName, $entityManager); $metadata = $this->getClassMetadata($entityName, $entityManager);
array_map( $ui->table(
[$table, 'addRow'], ['Field', 'Value'],
array_merge( array_merge(
[ [
$this->formatField('Name', $metadata->name), $this->formatField('Name', $metadata->name),
@ -125,8 +122,6 @@ EOT
$this->formatMappings($metadata->fieldMappings) $this->formatMappings($metadata->fieldMappings)
) )
); );
$table->render();
} }
/** /**
@ -138,10 +133,9 @@ EOT
*/ */
private function getMappedEntities(EntityManagerInterface $entityManager) private function getMappedEntities(EntityManagerInterface $entityManager)
{ {
$entityClassNames = $entityManager $entityClassNames = $entityManager->getConfiguration()
->getConfiguration() ->getMetadataDriverImpl()
->getMetadataDriverImpl() ->getAllClassNames();
->getAllClassNames();
if ( ! $entityClassNames) { if ( ! $entityClassNames) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
@ -219,11 +213,7 @@ EOT
} }
if (is_array($value)) { if (is_array($value)) {
if (defined('JSON_UNESCAPED_UNICODE') && defined('JSON_UNESCAPED_SLASHES')) { return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
return json_encode($value);
} }
if (is_object($value)) { if (is_object($value)) {
@ -285,14 +275,6 @@ EOT
*/ */
private function formatEntityListeners(array $entityListeners) private function formatEntityListeners(array $entityListeners)
{ {
return $this->formatField( return $this->formatField('Entity listeners', array_map('get_class', $entityListeners));
'Entity listeners',
array_map(
function ($entityListener) {
return get_class($entityListener);
},
$entityListeners
)
);
} }
} }

View File

@ -19,12 +19,13 @@
namespace Doctrine\ORM\Tools\Console\Command; namespace Doctrine\ORM\Tools\Console\Command;
use Doctrine\Common\Util\Debug;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\Common\Util\Debug; use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to execute DQL queries in a given EntityManager. * Command to execute DQL queries in a given EntityManager.
@ -43,39 +44,15 @@ class RunDqlCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:run-dql')
->setName('orm:run-dql') ->setDescription('Executes arbitrary DQL directly from the command line')
->setDescription('Executes arbitrary DQL directly from the command line.') ->addArgument('dql', InputArgument::REQUIRED, 'The DQL to execute.')
->setDefinition( ->addOption('hydrate', null, InputOption::VALUE_REQUIRED, 'Hydration mode of result set. Should be either: object, array, scalar or single-scalar.', 'object')
[ ->addOption('first-result', null, InputOption::VALUE_REQUIRED, 'The first result in the result set.')
new InputArgument('dql', InputArgument::REQUIRED, 'The DQL to execute.'), ->addOption('max-result', null, InputOption::VALUE_REQUIRED, 'The maximum number of results in the result set.')
new InputOption( ->addOption('depth', null, InputOption::VALUE_REQUIRED, 'Dumping depth of Entity graph.', 7)
'hydrate', null, InputOption::VALUE_REQUIRED, ->addOption('show-sql', null, InputOption::VALUE_NONE, 'Dump generated SQL instead of executing query')
'Hydration mode of result set. Should be either: object, array, scalar or single-scalar.', ->setHelp('Executes arbitrary DQL directly from the command line.');
'object'
),
new InputOption(
'first-result', null, InputOption::VALUE_REQUIRED,
'The first result in the result set.'
),
new InputOption(
'max-result', null, InputOption::VALUE_REQUIRED,
'The maximum number of results in the result set.'
),
new InputOption(
'depth', null, InputOption::VALUE_REQUIRED,
'Dumping depth of Entity graph.', 7
),
new InputOption(
'show-sql', null, InputOption::VALUE_NONE,
'Dump generated SQL instead of executing query'
)
]
)
->setHelp(<<<EOT
Executes arbitrary DQL directly from the command line.
EOT
);
} }
/** /**
@ -83,17 +60,19 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
/* @var $em \Doctrine\ORM\EntityManagerInterface */ /* @var $em \Doctrine\ORM\EntityManagerInterface */
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
if (($dql = $input->getArgument('dql')) === null) { if (($dql = $input->getArgument('dql')) === null) {
throw new \RuntimeException("Argument 'DQL' is required in order to execute this command correctly."); throw new \RuntimeException("Argument 'dql' is required in order to execute this command correctly.");
} }
$depth = $input->getOption('depth'); $depth = $input->getOption('depth');
if ( ! is_numeric($depth)) { if ( ! is_numeric($depth)) {
throw new \LogicException("Option 'depth' must contains an integer value"); throw new \LogicException("Option 'depth' must contain an integer value");
} }
$hydrationModeName = $input->getOption('hydrate'); $hydrationModeName = $input->getOption('hydrate');
@ -109,7 +88,7 @@ EOT
if (($firstResult = $input->getOption('first-result')) !== null) { if (($firstResult = $input->getOption('first-result')) !== null) {
if ( ! is_numeric($firstResult)) { if ( ! is_numeric($firstResult)) {
throw new \LogicException("Option 'first-result' must contains an integer value"); throw new \LogicException("Option 'first-result' must contain an integer value");
} }
$query->setFirstResult((int) $firstResult); $query->setFirstResult((int) $firstResult);
@ -117,19 +96,19 @@ EOT
if (($maxResult = $input->getOption('max-result')) !== null) { if (($maxResult = $input->getOption('max-result')) !== null) {
if ( ! is_numeric($maxResult)) { if ( ! is_numeric($maxResult)) {
throw new \LogicException("Option 'max-result' must contains an integer value"); throw new \LogicException("Option 'max-result' must contain an integer value");
} }
$query->setMaxResults((int) $maxResult); $query->setMaxResults((int) $maxResult);
} }
if ($input->getOption('show-sql')) { if ($input->getOption('show-sql')) {
$output->writeln(Debug::dump($query->getSQL(), 2, true, false)); $ui->text($query->getSQL());
return; return;
} }
$resultSet = $query->execute([], constant($hydrationMode)); $resultSet = $query->execute([], constant($hydrationMode));
$output->writeln(Debug::dump($resultSet, $input->getOption('depth'), true, false)); $ui->text(Debug::dump($resultSet, $input->getOption('depth'), true, false));
} }
} }

View File

@ -19,10 +19,11 @@
namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; namespace Doctrine\ORM\Tools\Console\Command\SchemaTool;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Style\SymfonyStyle;
use Doctrine\ORM\Tools\SchemaTool;
/** /**
* Base class for CreateCommand, DropCommand and UpdateCommand. * Base class for CreateCommand, DropCommand and UpdateCommand.
@ -44,13 +45,15 @@ abstract class AbstractCommand extends Command
* *
* @return null|int Null or 0 if everything went fine, or an error code. * @return null|int Null or 0 if everything went fine, or an error code.
*/ */
abstract protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas); abstract protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui);
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$emHelper = $this->getHelper('em'); $emHelper = $this->getHelper('em');
/* @var $em \Doctrine\ORM\EntityManager */ /* @var $em \Doctrine\ORM\EntityManager */
@ -58,15 +61,12 @@ abstract class AbstractCommand extends Command
$metadatas = $em->getMetadataFactory()->getAllMetadata(); $metadatas = $em->getMetadataFactory()->getAllMetadata();
if ( ! empty($metadatas)) { if (empty($metadatas)) {
// Create SchemaTool $ui->success('No Metadata Classes to process.');
$tool = new SchemaTool($em);
return $this->executeSchemaCommand($input, $output, $tool, $metadatas);
} else {
$output->writeln('No Metadata Classes to process.');
return 0; return 0;
} }
return $this->executeSchemaCommand($input, $output, new SchemaTool($em), $metadatas, $ui);
} }
} }

View File

@ -19,10 +19,11 @@
namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; namespace Doctrine\ORM\Tools\Console\Command\SchemaTool;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Tools\SchemaTool; use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to create the database schema for a set of classes based on their mappings. * Command to create the database schema for a set of classes based on their mappings.
@ -41,20 +42,10 @@ class CreateCommand extends AbstractCommand
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:schema-tool:create')
->setName('orm:schema-tool:create') ->setDescription('Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output')
->setDescription( ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Instead of trying to apply generated SQLs into EntityManager Storage Connection, output them.')
'Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output.' ->setHelp(<<<EOT
)
->setDefinition(
[
new InputOption(
'dump-sql', null, InputOption::VALUE_NONE,
'Instead of trying to apply generated SQLs into EntityManager Storage Connection, output them.'
)
]
)
->setHelp(<<<EOT
Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output. Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output.
<comment>Hint:</comment> If you have a database with tables that should not be managed <comment>Hint:</comment> If you have a database with tables that should not be managed
@ -63,25 +54,37 @@ on a global level:
\$config->setFilterSchemaAssetsExpression(\$regexp); \$config->setFilterSchemaAssetsExpression(\$regexp);
EOT EOT
); );
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas) protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui)
{ {
if ($input->getOption('dump-sql')) { $dumpSql = true === $input->getOption('dump-sql');
$sqls = $schemaTool->getCreateSchemaSql($metadatas);
$output->writeln(implode(';' . PHP_EOL, $sqls) . ';');
} else {
$output->writeln('ATTENTION: This operation should not be executed in a production environment.' . PHP_EOL);
$output->writeln('Creating database schema...'); if ($dumpSql) {
$schemaTool->createSchema($metadatas); $sqls = $schemaTool->getCreateSchemaSql($metadatas);
$output->writeln('Database schema created successfully!'); $ui->text('The following SQL statements will be executed:');
$ui->newLine();
foreach ($sqls as $sql) {
$ui->text(sprintf(' %s;', $sql));
}
return 0;
} }
$ui->caution('This operation should not be executed in a production environment!');
$ui->text('Creating database schema...');
$ui->newLine();
$schemaTool->createSchema($metadatas);
$ui->success('Database schema created successfully!');
return 0; return 0;
} }
} }

View File

@ -19,10 +19,11 @@
namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; namespace Doctrine\ORM\Tools\Console\Command\SchemaTool;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Tools\SchemaTool; use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to drop the database schema for a set of classes based on their mappings. * Command to drop the database schema for a set of classes based on their mappings.
@ -41,28 +42,12 @@ class DropCommand extends AbstractCommand
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:schema-tool:drop')
->setName('orm:schema-tool:drop') ->setDescription('Drop the complete database schema of EntityManager Storage Connection or generate the corresponding SQL output')
->setDescription( ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Instead of trying to apply generated SQLs into EntityManager Storage Connection, output them.')
'Drop the complete database schema of EntityManager Storage Connection or generate the corresponding SQL output.' ->addOption('force', 'f', InputOption::VALUE_NONE, "Don't ask for the deletion of the database, but force the operation to run.")
) ->addOption('full-database', null, InputOption::VALUE_NONE, 'Instead of using the Class Metadata to detect the database table schema, drop ALL assets that the database contains.')
->setDefinition( ->setHelp(<<<EOT
[
new InputOption(
'dump-sql', null, InputOption::VALUE_NONE,
'Instead of trying to apply generated SQLs into EntityManager Storage Connection, output them.'
),
new InputOption(
'force', 'f', InputOption::VALUE_NONE,
"Don't ask for the deletion of the database, but force the operation to run."
),
new InputOption(
'full-database', null, InputOption::VALUE_NONE,
'Instead of using the Class Metadata to detect the database table schema, drop ALL assets that the database contains.'
),
]
)
->setHelp(<<<EOT
Processes the schema and either drop the database schema of EntityManager Storage Connection or generate the SQL output. Processes the schema and either drop the database schema of EntityManager Storage Connection or generate the SQL output.
Beware that the complete database is dropped by this command, even tables that are not relevant to your metadata model. Beware that the complete database is dropped by this command, even tables that are not relevant to your metadata model.
@ -72,29 +57,37 @@ on a global level:
\$config->setFilterSchemaAssetsExpression(\$regexp); \$config->setFilterSchemaAssetsExpression(\$regexp);
EOT EOT
); );
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas) protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui)
{ {
$isFullDatabaseDrop = $input->getOption('full-database'); $isFullDatabaseDrop = $input->getOption('full-database');
$dumpSql = true === $input->getOption('dump-sql');
$force = true === $input->getOption('force');
if ($input->getOption('dump-sql')) { if ($dumpSql) {
if ($isFullDatabaseDrop) { if ($isFullDatabaseDrop) {
$sqls = $schemaTool->getDropDatabaseSQL(); $sqls = $schemaTool->getDropDatabaseSQL();
} else { } else {
$sqls = $schemaTool->getDropSchemaSQL($metadatas); $sqls = $schemaTool->getDropSchemaSQL($metadatas);
} }
$output->writeln(implode(';' . PHP_EOL, $sqls)); $ui->text('The following SQL statements will be executed:');
$ui->newLine();
foreach ($sqls as $sql) {
$ui->text(sprintf(' %s;', $sql));
}
return 0; return 0;
} }
if ($input->getOption('force')) { if ($force) {
$output->writeln('Dropping database schema...'); $ui->text('Dropping database schema...');
$ui->newLine();
if ($isFullDatabaseDrop) { if ($isFullDatabaseDrop) {
$schemaTool->dropDatabase(); $schemaTool->dropDatabase();
@ -102,12 +95,12 @@ EOT
$schemaTool->dropSchema($metadatas); $schemaTool->dropSchema($metadatas);
} }
$output->writeln('Database schema dropped successfully!'); $ui->success('Database schema dropped successfully!');
return 0; return 0;
} }
$output->writeln('<comment>ATTENTION</comment>: This operation should not be executed in a production environment.' . PHP_EOL); $ui->caution('This operation should not be executed in a production environment!');
if ($isFullDatabaseDrop) { if ($isFullDatabaseDrop) {
$sqls = $schemaTool->getDropDatabaseSQL(); $sqls = $schemaTool->getDropDatabaseSQL();
@ -115,18 +108,23 @@ EOT
$sqls = $schemaTool->getDropSchemaSQL($metadatas); $sqls = $schemaTool->getDropSchemaSQL($metadatas);
} }
if (count($sqls)) { if (empty($sqls)) {
$output->writeln(sprintf('The Schema-Tool would execute <info>"%s"</info> queries to update the database.', count($sqls))); $ui->success('Nothing to drop. The database is empty!');
$output->writeln('Please run the operation by passing one - or both - of the following options:');
$output->writeln(sprintf(' <info>%s --force</info> to execute the command', $this->getName())); return 0;
$output->writeln(sprintf(' <info>%s --dump-sql</info> to dump the SQL statements to the screen', $this->getName()));
return 1;
} }
$output->writeln('Nothing to drop. The database is empty!'); $ui->text(
[
sprintf('The Schema-Tool would execute <info>"%s"</info> queries to update the database.', count($sqls)),
'',
'Please run the operation by passing one - or both - of the following options:',
'',
sprintf(' <info>%s --force</info> to execute the command', $this->getName()),
sprintf(' <info>%s --dump-sql</info> to dump the SQL statements to the screen', $this->getName()),
]
);
return 0; return 1;
} }
} }

View File

@ -19,10 +19,11 @@
namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; namespace Doctrine\ORM\Tools\Console\Command\SchemaTool;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Tools\SchemaTool; use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to generate the SQL needed to update the database schema to match * Command to generate the SQL needed to update the database schema to match
@ -48,30 +49,12 @@ class UpdateCommand extends AbstractCommand
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName($this->name)
->setName($this->name) ->setDescription('Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata')
->setDescription( ->addOption('complete', null, InputOption::VALUE_NONE, 'If defined, all assets of the database which are not relevant to the current metadata will be dropped.')
'Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata.' ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Dumps the generated SQL statements to the screen (does not execute them).')
) ->addOption('force', 'f', InputOption::VALUE_NONE, 'Causes the generated SQL statements to be physically executed against your database.')
->setDefinition( ->setHelp(<<<EOT
[
new InputOption(
'complete', null, InputOption::VALUE_NONE,
'If defined, all assets of the database which are not relevant to the current metadata will be dropped.'
),
new InputOption(
'dump-sql', null, InputOption::VALUE_NONE,
'Dumps the generated SQL statements to the screen (does not execute them).'
),
new InputOption(
'force', 'f', InputOption::VALUE_NONE,
'Causes the generated SQL statements to be physically executed against your database.'
),
]
);
$this->setHelp(<<<EOT
The <info>%command.name%</info> command generates the SQL needed to The <info>%command.name%</info> command generates the SQL needed to
synchronize the database schema with the current mapping metadata of the synchronize the database schema with the current mapping metadata of the
default entity manager. default entity manager.
@ -101,21 +84,21 @@ on a global level:
\$config->setFilterSchemaAssetsExpression(\$regexp); \$config->setFilterSchemaAssetsExpression(\$regexp);
EOT EOT
); );
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas) protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui)
{ {
// Defining if update is complete or not (--complete not defined means $saveMode = true) // Defining if update is complete or not (--complete not defined means $saveMode = true)
$saveMode = ! $input->getOption('complete'); $saveMode = ! $input->getOption('complete');
$sqls = $schemaTool->getUpdateSchemaSql($metadatas, $saveMode); $sqls = $schemaTool->getUpdateSchemaSql($metadatas, $saveMode);
if (0 === count($sqls)) { if (empty($sqls)) {
$output->writeln('Nothing to update - your database is already in sync with the current entity metadata.'); $ui->success('Nothing to update - your database is already in sync with the current entity metadata.');
return 0; return 0;
} }
@ -124,35 +107,52 @@ EOT
$force = true === $input->getOption('force'); $force = true === $input->getOption('force');
if ($dumpSql) { if ($dumpSql) {
$output->writeln(implode(';' . PHP_EOL, $sqls) . ';'); $ui->text('The following SQL statements will be executed:');
$ui->newLine();
foreach ($sqls as $sql) {
$ui->text(sprintf(' %s;', $sql));
}
} }
if ($force) { if ($force) {
if ($dumpSql) { if ($dumpSql) {
$output->writeln(''); $ui->newLine();
} }
$output->writeln('Updating database schema...'); $ui->text('Updating database schema...');
$ui->newLine();
$schemaTool->updateSchema($metadatas, $saveMode); $schemaTool->updateSchema($metadatas, $saveMode);
$pluralization = (1 === count($sqls)) ? 'query was' : 'queries were'; $pluralization = (1 === count($sqls)) ? 'query was' : 'queries were';
$output->writeln(sprintf('Database schema updated successfully! "<info>%s</info>" %s executed', count($sqls), $pluralization)); $ui->text(sprintf(' <info>%s</info> %s executed', count($sqls), $pluralization));
$ui->success('Database schema updated successfully!');
} }
if ($dumpSql || $force) { if ($dumpSql || $force) {
return 0; return 0;
} }
$output->writeln('<comment>ATTENTION</comment>: This operation should not be executed in a production environment.'); $ui->caution(
$output->writeln(' Use the incremental update to detect changes during development and use'); [
$output->writeln(' the SQL DDL provided to manually update your database in production.'); 'This operation should not be executed in a production environment!',
$output->writeln(''); '',
'Use the incremental update to detect changes during development and use',
'the SQL DDL provided to manually update your database in production.',
]
);
$output->writeln(sprintf('The Schema-Tool would execute <info>"%s"</info> queries to update the database.', count($sqls))); $ui->text(
$output->writeln('Please run the operation by passing one - or both - of the following options:'); [
sprintf('The Schema-Tool would execute <info>"%s"</info> queries to update the database.', count($sqls)),
$output->writeln(sprintf(' <info>%s --force</info> to execute the command', $this->getName())); '',
$output->writeln(sprintf(' <info>%s --dump-sql</info> to dump the SQL statements to the screen', $this->getName())); 'Please run the operation by passing one - or both - of the following options:',
'',
sprintf(' <info>%s --force</info> to execute the command', $this->getName()),
sprintf(' <info>%s --dump-sql</info> to dump the SQL statements to the screen', $this->getName()),
]
);
return 1; return 1;
} }

View File

@ -19,11 +19,12 @@
namespace Doctrine\ORM\Tools\Console\Command; namespace Doctrine\ORM\Tools\Console\Command;
use Doctrine\ORM\Tools\SchemaValidator;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Tools\SchemaValidator; use Symfony\Component\Console\Style\SymfonyStyle;
/** /**
* Command to validate that the current mapping is valid. * Command to validate that the current mapping is valid.
@ -43,26 +44,11 @@ class ValidateSchemaCommand extends Command
*/ */
protected function configure() protected function configure()
{ {
$this $this->setName('orm:validate-schema')
->setName('orm:validate-schema') ->setDescription('Validate the mapping files')
->setDescription('Validate the mapping files.') ->addOption('skip-mapping', null, InputOption::VALUE_NONE, 'Skip the mapping validation check')
->addOption( ->addOption('skip-sync', null, InputOption::VALUE_NONE, 'Skip checking if the mapping is in sync with the database')
'skip-mapping', ->setHelp('Validate that the mapping files are correct and in sync with the database.');
null,
InputOption::VALUE_NONE,
'Skip the mapping validation check'
)
->addOption(
'skip-sync',
null,
InputOption::VALUE_NONE,
'Skip checking if the mapping is in sync with the database'
)
->setHelp(
<<<EOT
'Validate that the mapping files are correct and in sync with the database.'
EOT
);
} }
/** /**
@ -70,35 +56,43 @@ EOT
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$ui = new SymfonyStyle($input, $output);
$em = $this->getHelper('em')->getEntityManager(); $em = $this->getHelper('em')->getEntityManager();
$validator = new SchemaValidator($em); $validator = new SchemaValidator($em);
$exit = 0; $exit = 0;
$ui->section('Mapping');
if ($input->getOption('skip-mapping')) { if ($input->getOption('skip-mapping')) {
$output->writeln('<comment>[Mapping] Skipped mapping check.</comment>'); $ui->text('<comment>[SKIPPED] The mapping was not checked.</comment>');
} elseif ($errors = $validator->validateMapping()) { } elseif ($errors = $validator->validateMapping()) {
foreach ($errors as $className => $errorMessages) { foreach ($errors as $className => $errorMessages) {
$output->writeln("<error>[Mapping] FAIL - The entity-class '" . $className . "' mapping is invalid:</error>"); $ui->text(
sprintf(
'<error>[FAIL]</error> The entity-class <comment>%s</comment> mapping is invalid:',
$className
)
);
foreach ($errorMessages as $errorMessage) { $ui->listing($errorMessages);
$output->writeln('* ' . $errorMessage); $ui->newLine();
}
$output->writeln('');
} }
++$exit; ++$exit;
} else { } else {
$output->writeln('<info>[Mapping] OK - The mapping files are correct.</info>'); $ui->success('The mapping files are correct.');
} }
$ui->section('Database');
if ($input->getOption('skip-sync')) { if ($input->getOption('skip-sync')) {
$output->writeln('<comment>[Database] SKIPPED - The database was not checked for synchronicity.</comment>'); $ui->text('<comment>[SKIPPED] The database was not checked for synchronicity.</comment>');
} elseif (!$validator->schemaInSyncWithMetadata()) { } elseif ( ! $validator->schemaInSyncWithMetadata()) {
$output->writeln('<error>[Database] FAIL - The database schema is not in sync with the current mapping file.</error>'); $ui->error('The database schema is not in sync with the current mapping file.');
$exit += 2; $exit += 2;
} else { } else {
$output->writeln('<info>[Database] OK - The database schema is in sync with the mapping files.</info>'); $ui->success('The database schema is in sync with the mapping files.');
} }
return $exit; return $exit;

View File

@ -19,6 +19,10 @@
bootstrap="./tests/Doctrine/Tests/TestInit.php" bootstrap="./tests/Doctrine/Tests/TestInit.php"
> >
<php>
<env name="COLUMNS" value="120"/>
</php>
<testsuites> <testsuites>
<testsuite name="Doctrine ORM Test Suite"> <testsuite name="Doctrine ORM Test Suite">
<directory>./tests/Doctrine/Tests/ORM</directory> <directory>./tests/Doctrine/Tests/ORM</directory>

View File

@ -30,76 +30,90 @@ class ClearCacheCollectionRegionCommandTest extends OrmFunctionalTestCase
$this->enableSecondLevelCache(); $this->enableSecondLevelCache();
parent::setUp(); parent::setUp();
$this->command = new CollectionRegionCommand();
$this->application = new Application(); $this->application = new Application();
$this->command = new CollectionRegionCommand(); $this->application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($this->_em)]));
$this->application->setHelperSet(new HelperSet(
[
'em' => new EntityManagerHelper($this->_em)
]
));
$this->application->add($this->command); $this->application->add($this->command);
} }
public function testClearAllRegion() public function testClearAllRegion()
{ {
$command = $this->application->find('orm:clear-cache:region:collection'); $command = $this->application->find('orm:clear-cache:region:collection');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'--all' => true, '--all' => true,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Clearing all second-level cache collection regions' . PHP_EOL, $tester->getDisplay()); self::assertContains(' // Clearing all second-level cache collection regions', $tester->getDisplay());
} }
public function testClearByOwnerEntityClassName() public function testClearByOwnerEntityClassName()
{ {
$command = $this->application->find('orm:clear-cache:region:collection'); $command = $this->application->find('orm:clear-cache:region:collection');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'owner-class' => State::class, 'owner-class' => State::class,
'association' => 'cities', 'association' => 'cities',
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Clearing second-level cache for collection "Doctrine\Tests\Models\Cache\State#cities"' . PHP_EOL, $tester->getDisplay()); self::assertContains(
' // Clearing second-level cache for collection "Doctrine\Tests\Models\Cache\State#cities"',
$tester->getDisplay()
);
} }
public function testClearCacheEntryName() public function testClearCacheEntryName()
{ {
$command = $this->application->find('orm:clear-cache:region:collection'); $command = $this->application->find('orm:clear-cache:region:collection');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'owner-class' => State::class, 'owner-class' => State::class,
'association' => 'cities', 'association' => 'cities',
'owner-id' => 1, 'owner-id' => 1,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Clearing second-level cache entry for collection "Doctrine\Tests\Models\Cache\State#cities" owner entity identified by "1"' . PHP_EOL, $tester->getDisplay()); self::assertContains(
' // Clearing second-level cache entry for collection "Doctrine\Tests\Models\Cache\State#cities" owner',
$tester->getDisplay()
);
self::assertContains(' // entity identified by "1"', $tester->getDisplay());
} }
public function testFlushRegionName() public function testFlushRegionName()
{ {
$command = $this->application->find('orm:clear-cache:region:collection'); $command = $this->application->find('orm:clear-cache:region:collection');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'owner-class' => State::class, 'owner-class' => State::class,
'association' => 'cities', 'association' => 'cities',
'--flush' => true, '--flush' => true,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Flushing cache provider configured for "Doctrine\Tests\Models\Cache\State#cities"' . PHP_EOL, $tester->getDisplay()); self::assertContains(
' // Flushing cache provider configured for "Doctrine\Tests\Models\Cache\State#cities"',
$tester->getDisplay()
);
} }
} }

View File

@ -30,73 +30,87 @@ class ClearCacheEntityRegionCommandTest extends OrmFunctionalTestCase
$this->enableSecondLevelCache(); $this->enableSecondLevelCache();
parent::setUp(); parent::setUp();
$this->command = new EntityRegionCommand();
$this->application = new Application(); $this->application = new Application();
$this->command = new EntityRegionCommand(); $this->application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($this->_em)]));
$this->application->setHelperSet(new HelperSet(
[
'em' => new EntityManagerHelper($this->_em)
]
));
$this->application->add($this->command); $this->application->add($this->command);
} }
public function testClearAllRegion() public function testClearAllRegion()
{ {
$command = $this->application->find('orm:clear-cache:region:entity'); $command = $this->application->find('orm:clear-cache:region:entity');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'--all' => true, '--all' => true,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Clearing all second-level cache entity regions' . PHP_EOL, $tester->getDisplay()); self::assertContains(' // Clearing all second-level cache entity regions', $tester->getDisplay());
} }
public function testClearByEntityClassName() public function testClearByEntityClassName()
{ {
$command = $this->application->find('orm:clear-cache:region:entity'); $command = $this->application->find('orm:clear-cache:region:entity');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'entity-class' => Country::class, 'entity-class' => Country::class,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Clearing second-level cache for entity "Doctrine\Tests\Models\Cache\Country"' . PHP_EOL, $tester->getDisplay()); self::assertContains(
' // Clearing second-level cache for entity "Doctrine\Tests\Models\Cache\Country"',
$tester->getDisplay()
);
} }
public function testClearCacheEntryName() public function testClearCacheEntryName()
{ {
$command = $this->application->find('orm:clear-cache:region:entity'); $command = $this->application->find('orm:clear-cache:region:entity');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'entity-class' => Country::class, 'entity-class' => Country::class,
'entity-id' => 1, 'entity-id' => 1,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Clearing second-level cache entry for entity "Doctrine\Tests\Models\Cache\Country" identified by "1"' . PHP_EOL, $tester->getDisplay()); self::assertContains(
' // Clearing second-level cache entry for entity "Doctrine\Tests\Models\Cache\Country" identified by',
$tester->getDisplay()
);
self::assertContains(' // "1"', $tester->getDisplay());
} }
public function testFlushRegionName() public function testFlushRegionName()
{ {
$command = $this->application->find('orm:clear-cache:region:entity'); $command = $this->application->find('orm:clear-cache:region:entity');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'entity-class' => Country::class, 'entity-class' => Country::class,
'--flush' => true, '--flush' => true,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Flushing cache provider configured for entity named "Doctrine\Tests\Models\Cache\Country"' . PHP_EOL, $tester->getDisplay()); self::assertContains(
' // Flushing cache provider configured for entity named "Doctrine\Tests\Models\Cache\Country"',
$tester->getDisplay()
);
} }
} }

View File

@ -4,10 +4,10 @@ namespace Doctrine\Tests\ORM\Tools\Console\Command;
use Doctrine\ORM\Tools\Console\Command\ClearCache\QueryRegionCommand; use Doctrine\ORM\Tools\Console\Command\ClearCache\QueryRegionCommand;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper; use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Application;
use Doctrine\Tests\OrmFunctionalTestCase; use Doctrine\Tests\OrmFunctionalTestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Tester\CommandTester;
/** /**
* @group DDC-2183 * @group DDC-2183
@ -29,72 +29,84 @@ class ClearCacheQueryRegionCommandTest extends OrmFunctionalTestCase
$this->enableSecondLevelCache(); $this->enableSecondLevelCache();
parent::setUp(); parent::setUp();
$this->command = new QueryRegionCommand();
$this->application = new Application(); $this->application = new Application();
$this->command = new QueryRegionCommand(); $this->application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($this->_em)]));
$this->application->setHelperSet(new HelperSet(
[
'em' => new EntityManagerHelper($this->_em)
]
));
$this->application->add($this->command); $this->application->add($this->command);
} }
public function testClearAllRegion() public function testClearAllRegion()
{ {
$command = $this->application->find('orm:clear-cache:region:query'); $command = $this->application->find('orm:clear-cache:region:query');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'--all' => true, '--all' => true,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Clearing all second-level cache query regions' . PHP_EOL, $tester->getDisplay()); self::assertContains(' // Clearing all second-level cache query regions', $tester->getDisplay());
} }
public function testClearDefaultRegionName() public function testClearDefaultRegionName()
{ {
$command = $this->application->find('orm:clear-cache:region:query'); $command = $this->application->find('orm:clear-cache:region:query');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'region-name' => null, 'region-name' => null,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Clearing second-level cache query region named "query_cache_region"' . PHP_EOL, $tester->getDisplay()); self::assertContains(
' // Clearing second-level cache query region named "query_cache_region"',
$tester->getDisplay()
);
} }
public function testClearByRegionName() public function testClearByRegionName()
{ {
$command = $this->application->find('orm:clear-cache:region:query'); $command = $this->application->find('orm:clear-cache:region:query');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'region-name' => 'my_region', 'region-name' => 'my_region',
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Clearing second-level cache query region named "my_region"' . PHP_EOL, $tester->getDisplay()); self::assertContains(
' // Clearing second-level cache query region named "my_region"',
$tester->getDisplay()
);
} }
public function testFlushRegionName() public function testFlushRegionName()
{ {
$command = $this->application->find('orm:clear-cache:region:query'); $command = $this->application->find('orm:clear-cache:region:query');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'region-name' => 'my_region', 'region-name' => 'my_region',
'--flush' => true, '--flush' => true,
], ['decorated' => false] ],
['decorated' => false]
); );
$this->assertEquals('Flushing cache provider configured for second-level cache query region named "my_region"' . PHP_EOL, $tester->getDisplay()); self::assertContains(
' // Flushing cache provider configured for second-level cache query region named "my_region"',
$tester->getDisplay()
);
} }
} }

View File

@ -2,18 +2,18 @@
namespace Doctrine\Tests\ORM\Tools\Console\Command; namespace Doctrine\Tests\ORM\Tools\Console\Command;
use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository; use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Tools\Console\Command\GenerateRepositoriesCommand; use Doctrine\ORM\Tools\Console\Command\GenerateRepositoriesCommand;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper; use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
use Doctrine\Tests\Models\DDC3231\DDC3231EntityRepository; use Doctrine\Tests\Models\DDC3231\DDC3231EntityRepository;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Application;
use Doctrine\Tests\OrmFunctionalTestCase; use Doctrine\Tests\OrmFunctionalTestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Tester\CommandTester;
/**
* GenerateRepositoriesCommandTest
*/
class GenerateRepositoriesCommandTest extends OrmFunctionalTestCase class GenerateRepositoriesCommandTest extends OrmFunctionalTestCase
{ {
/** /**
@ -34,25 +34,12 @@ class GenerateRepositoriesCommandTest extends OrmFunctionalTestCase
\mkdir($this->path); \mkdir($this->path);
$metadataDriver = $this->_em->getConfiguration()->getMetadataDriverImpl(); $metadataDriver = $this->_em->getConfiguration()->getMetadataDriverImpl();
$metadataDriver->addPaths([__DIR__ . '/../../../../Models/DDC3231/']);
$metadataDriver->addPaths(
[
__DIR__ . '/../../../../Models/DDC3231/'
]
);
$this->application = new Application(); $this->application = new Application();
$this->application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($this->_em)]));
$this->application->setHelperSet(new HelperSet(
[
'em' => new EntityManagerHelper($this->_em)
]
));
$this->application->add(new GenerateRepositoriesCommand()); $this->application->add(new GenerateRepositoriesCommand());
} }
/** /**
@ -88,20 +75,20 @@ class GenerateRepositoriesCommandTest extends OrmFunctionalTestCase
$cname = 'Doctrine\Tests\Models\DDC3231\DDC3231User1Repository'; $cname = 'Doctrine\Tests\Models\DDC3231\DDC3231User1Repository';
$fname = str_replace('\\', DIRECTORY_SEPARATOR, $cname) . '.php'; $fname = str_replace('\\', DIRECTORY_SEPARATOR, $cname) . '.php';
$this->assertFileExists($this->path . DIRECTORY_SEPARATOR . $fname); self::assertFileExists($this->path . DIRECTORY_SEPARATOR . $fname);
$this->assertFileExists($this->path . DIRECTORY_SEPARATOR . 'DDC3231User1NoNamespaceRepository.php'); self::assertFileExists($this->path . DIRECTORY_SEPARATOR . 'DDC3231User1NoNamespaceRepository.php');
require $this->path . DIRECTORY_SEPARATOR . $fname; require $this->path . DIRECTORY_SEPARATOR . $fname;
require $this->path . DIRECTORY_SEPARATOR . 'DDC3231User1NoNamespaceRepository.php'; require $this->path . DIRECTORY_SEPARATOR . 'DDC3231User1NoNamespaceRepository.php';
$this->assertTrue(class_exists($cname)); self::assertTrue(class_exists($cname));
$this->assertTrue(class_exists('DDC3231User1NoNamespaceRepository')); self::assertTrue(class_exists('DDC3231User1NoNamespaceRepository'));
$repo1 = new \ReflectionClass($cname); $repo1 = new \ReflectionClass($cname);
$repo2 = new \ReflectionClass('DDC3231User1NoNamespaceRepository'); $repo2 = new \ReflectionClass('DDC3231User1NoNamespaceRepository');
$this->assertSame(EntityRepository::class, $repo1->getParentClass()->getName()); self::assertSame(EntityRepository::class, $repo1->getParentClass()->getName());
$this->assertSame(EntityRepository::class, $repo2->getParentClass()->getName()); self::assertSame(EntityRepository::class, $repo2->getParentClass()->getName());
} }
public function testGenerateRepositoriesCustomDefaultRepository() public function testGenerateRepositoriesCustomDefaultRepository()
@ -111,20 +98,20 @@ class GenerateRepositoriesCommandTest extends OrmFunctionalTestCase
$cname = 'Doctrine\Tests\Models\DDC3231\DDC3231User2Repository'; $cname = 'Doctrine\Tests\Models\DDC3231\DDC3231User2Repository';
$fname = str_replace('\\', DIRECTORY_SEPARATOR, $cname) . '.php'; $fname = str_replace('\\', DIRECTORY_SEPARATOR, $cname) . '.php';
$this->assertFileExists($this->path . DIRECTORY_SEPARATOR . $fname); self::assertFileExists($this->path . DIRECTORY_SEPARATOR . $fname);
$this->assertFileExists($this->path . DIRECTORY_SEPARATOR . 'DDC3231User2NoNamespaceRepository.php'); self::assertFileExists($this->path . DIRECTORY_SEPARATOR . 'DDC3231User2NoNamespaceRepository.php');
require $this->path . DIRECTORY_SEPARATOR . $fname; require $this->path . DIRECTORY_SEPARATOR . $fname;
require $this->path . DIRECTORY_SEPARATOR . 'DDC3231User2NoNamespaceRepository.php'; require $this->path . DIRECTORY_SEPARATOR . 'DDC3231User2NoNamespaceRepository.php';
$this->assertTrue(class_exists($cname)); self::assertTrue(class_exists($cname));
$this->assertTrue(class_exists('DDC3231User2NoNamespaceRepository')); self::assertTrue(class_exists('DDC3231User2NoNamespaceRepository'));
$repo1 = new \ReflectionClass($cname); $repo1 = new \ReflectionClass($cname);
$repo2 = new \ReflectionClass('DDC3231User2NoNamespaceRepository'); $repo2 = new \ReflectionClass('DDC3231User2NoNamespaceRepository');
$this->assertSame(DDC3231EntityRepository::class, $repo1->getParentClass()->getName()); self::assertSame(DDC3231EntityRepository::class, $repo1->getParentClass()->getName());
$this->assertSame(DDC3231EntityRepository::class, $repo2->getParentClass()->getName()); self::assertSame(DDC3231EntityRepository::class, $repo2->getParentClass()->getName());
} }
/** /**
@ -137,15 +124,50 @@ class GenerateRepositoriesCommandTest extends OrmFunctionalTestCase
$this->_em->getConfiguration()->setDefaultRepositoryClassName($defaultRepository); $this->_em->getConfiguration()->setDefaultRepositoryClassName($defaultRepository);
} }
$command = $this->application->find('orm:generate-repositories'); $command = $this->application->find('orm:generate-repositories');
$tester = new CommandTester($command); $tester = new CommandTester($command);
$tester->execute( $tester->execute(
[ [
'command' => $command->getName(), 'command' => $command->getName(),
'dest-path' => $this->path, 'dest-path' => $this->path,
'--filter' => $filter, '--filter' => $filter,
] ]
); );
} }
public function testNoMetadataClassesToProcess() : void
{
$configuration = $this->createMock(Configuration::class);
$metadataFactory = $this->createMock(ClassMetadataFactory::class);
$em = $this->createMock(EntityManagerInterface::class);
$configuration->method('getDefaultRepositoryClassName')
->willReturn('fooRepository');
$metadataFactory->method('getAllMetadata')
->willReturn([]);
$em->method('getMetadataFactory')
->willReturn($metadataFactory);
$em->method('getConfiguration')
->willReturn($configuration);
$application = new Application();
$application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($em)]));
$application->add(new GenerateRepositoriesCommand());
$command = $application->find('orm:generate-repositories');
$tester = new CommandTester($command);
$tester->execute(
[
'command' => $command->getName(),
'dest-path' => $this->path,
]
);
self::assertContains('[OK] No Metadata Classes to process.', $tester->getDisplay());
}
} }

View File

@ -2,6 +2,10 @@
namespace Doctrine\Tests\ORM\Tools\Console\Command; namespace Doctrine\Tests\ORM\Tools\Console\Command;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\MappingException;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper; use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
use Doctrine\Tests\Models\Cache\AttractionInfo; use Doctrine\Tests\Models\Cache\AttractionInfo;
use Doctrine\Tests\Models\Cache\City; use Doctrine\Tests\Models\Cache\City;
@ -33,23 +37,86 @@ class InfoCommandTest extends OrmFunctionalTestCase
parent::setUp(); parent::setUp();
$this->application = new Application(); $this->application = new Application();
$command = new InfoCommand();
$this->application->setHelperSet( $this->application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($this->_em)]));
new HelperSet(['em' => new EntityManagerHelper($this->_em)]) $this->application->add(new InfoCommand());
);
$this->application->add($command); $this->command = $this->application->find('orm:info');
$this->tester = new CommandTester($this->command);
$this->command = $this->application->find('orm:info');
$this->tester = new CommandTester($command);
} }
public function testListAllClasses() public function testListAllClasses()
{ {
$this->tester->execute(['command' => $this->command->getName()]); $this->tester->execute(['command' => $this->command->getName()]);
$this->assertContains(AttractionInfo::class, $this->tester->getDisplay()); self::assertContains(AttractionInfo::class, $this->tester->getDisplay());
$this->assertContains(City::class, $this->tester->getDisplay()); self::assertContains(City::class, $this->tester->getDisplay());
}
public function testEmptyEntityClassNames() : void
{
$mappingDriver = $this->createMock(MappingDriver::class);
$configuration = $this->createMock(Configuration::class);
$em = $this->createMock(EntityManagerInterface::class);
$mappingDriver->method('getAllClassNames')
->willReturn([]);
$configuration->method('getMetadataDriverImpl')
->willReturn($mappingDriver);
$em->method('getConfiguration')
->willReturn($configuration);
$application = new Application();
$application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($em)]));
$application->add(new InfoCommand());
$command = $application->find('orm:info');
$tester = new CommandTester($command);
$tester->execute(['command' => $command->getName()]);
self::assertContains(
' ! [CAUTION] You do not have any mapped Doctrine ORM entities according to the current configuration',
$tester->getDisplay()
);
self::assertContains(
' ! If you have entities or mapping files you should check your mapping configuration for errors.',
$tester->getDisplay()
);
}
public function testInvalidEntityClassMetadata() : void
{
$mappingDriver = $this->createMock(MappingDriver::class);
$configuration = $this->createMock(Configuration::class);
$em = $this->createMock(EntityManagerInterface::class);
$mappingDriver->method('getAllClassNames')
->willReturn(['InvalidEntity']);
$configuration->method('getMetadataDriverImpl')
->willReturn($mappingDriver);
$em->method('getConfiguration')
->willReturn($configuration);
$em->method('getClassMetadata')
->with('InvalidEntity')
->willThrowException(new MappingException('exception message'));
$application = new Application();
$application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($em)]));
$application->add(new InfoCommand());
$command = $application->find('orm:info');
$tester = new CommandTester($command);
$tester->execute(['command' => $command->getName()]);
self::assertContains('[FAIL] InvalidEntity', $tester->getDisplay());
self::assertContains('exception message', $tester->getDisplay());
} }
} }

View File

@ -37,32 +37,26 @@ class MappingDescribeCommandTest extends OrmFunctionalTestCase
parent::setUp(); parent::setUp();
$this->application = new Application(); $this->application = new Application();
$command = new MappingDescribeCommand(); $this->application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($this->_em)]));
$this->application->add(new MappingDescribeCommand());
$this->application->setHelperSet(new HelperSet(
[
'em' => new EntityManagerHelper($this->_em)
]
));
$this->application->add($command);
$this->command = $this->application->find('orm:mapping:describe'); $this->command = $this->application->find('orm:mapping:describe');
$this->tester = new CommandTester($command); $this->tester = new CommandTester($this->command);
} }
public function testShowSpecificFuzzySingle() public function testShowSpecificFuzzySingle()
{ {
$this->tester->execute( $this->tester->execute(
[ [
'command' => $this->command->getName(), 'command' => $this->command->getName(),
'entityName' => 'AttractionInfo', 'entityName' => 'AttractionInfo',
] ]
); );
$display = $this->tester->getDisplay(); $display = $this->tester->getDisplay();
$this->assertContains(AttractionInfo::class, $display);
$this->assertContains('Root entity name', $display); self::assertContains(AttractionInfo::class, $display);
self::assertContains('Root entity name', $display);
} }
/** /**
@ -73,8 +67,8 @@ class MappingDescribeCommandTest extends OrmFunctionalTestCase
{ {
$this->tester->execute( $this->tester->execute(
[ [
'command' => $this->command->getName(), 'command' => $this->command->getName(),
'entityName' => 'Attraction', 'entityName' => 'Attraction',
] ]
); );
} }
@ -87,8 +81,8 @@ class MappingDescribeCommandTest extends OrmFunctionalTestCase
{ {
$this->tester->execute( $this->tester->execute(
[ [
'command' => $this->command->getName(), 'command' => $this->command->getName(),
'entityName' => 'AttractionFooBar' 'entityName' => 'AttractionFooBar',
] ]
); );
} }

View File

@ -38,15 +38,10 @@ class RunDqlCommandTest extends OrmFunctionalTestCase
parent::setUp(); parent::setUp();
$this->command = new RunDqlCommand();
$this->application = new Application(); $this->application = new Application();
$this->command = new RunDqlCommand(); $this->application->setHelperSet(new HelperSet(['em' => new EntityManagerHelper($this->_em)]));
$this->application->setHelperSet(new HelperSet(
[
'em' => new EntityManagerHelper($this->_em)
]
));
$this->application->add($this->command); $this->application->add($this->command);
$this->tester = new CommandTester($this->command); $this->tester = new CommandTester($this->command);
@ -54,7 +49,7 @@ class RunDqlCommandTest extends OrmFunctionalTestCase
public function testCommandName() public function testCommandName()
{ {
$this->assertSame($this->command, $this->application->get('orm:run-dql')); self::assertSame($this->command, $this->application->get('orm:run-dql'));
} }
public function testWillRunQuery() public function testWillRunQuery()
@ -62,17 +57,17 @@ class RunDqlCommandTest extends OrmFunctionalTestCase
$this->_em->persist(new DateTimeModel()); $this->_em->persist(new DateTimeModel());
$this->_em->flush(); $this->_em->flush();
$this->assertSame( self::assertSame(
0, 0,
$this->tester->execute( $this->tester->execute(
[ [
'command' => $this->command->getName(), 'command' => $this->command->getName(),
'dql' => 'SELECT e FROM ' . DateTimeModel::class . ' e', 'dql' => 'SELECT e FROM ' . DateTimeModel::class . ' e',
] ]
) )
); );
$this->assertContains(DateTimeModel::class, $this->tester->getDisplay()); self::assertContains(DateTimeModel::class, $this->tester->getDisplay());
} }
public function testWillShowQuery() public function testWillShowQuery()
@ -80,17 +75,17 @@ class RunDqlCommandTest extends OrmFunctionalTestCase
$this->_em->persist(new DateTimeModel()); $this->_em->persist(new DateTimeModel());
$this->_em->flush(); $this->_em->flush();
$this->assertSame( self::assertSame(
0, 0,
$this->tester->execute( $this->tester->execute(
[ [
'command' => $this->command->getName(), 'command' => $this->command->getName(),
'dql' => 'SELECT e FROM ' . DateTimeModel::class . ' e', 'dql' => 'SELECT e FROM ' . DateTimeModel::class . ' e',
'--show-sql' => 'true' '--show-sql' => 'true',
] ]
) )
); );
$this->assertStringMatchesFormat('%Astring%sSELECT %a', $this->tester->getDisplay()); self::assertStringMatchesFormat('SELECT %a', trim($this->tester->getDisplay()));
} }
} }

View File

@ -19,6 +19,8 @@
<var name="tmpdb_username" value="travis" /> <var name="tmpdb_username" value="travis" />
<var name="tmpdb_password" value="" /> <var name="tmpdb_password" value="" />
<var name="tmpdb_port" value="3306"/> <var name="tmpdb_port" value="3306"/>
<env name="COLUMNS" value="120"/>
</php> </php>
<testsuites> <testsuites>

View File

@ -19,6 +19,8 @@
<var name="tmpdb_username" value="travis" /> <var name="tmpdb_username" value="travis" />
<var name="tmpdb_password" value="" /> <var name="tmpdb_password" value="" />
<var name="tmpdb_port" value="3306"/> <var name="tmpdb_port" value="3306"/>
<env name="COLUMNS" value="120"/>
</php> </php>
<testsuites> <testsuites>

View File

@ -22,6 +22,8 @@
<var name="tmpdb_username" value="postgres" /> <var name="tmpdb_username" value="postgres" />
<var name="tmpdb_password" value="" /> <var name="tmpdb_password" value="" />
<var name="tmpdb_port" value="5432"/> <var name="tmpdb_port" value="5432"/>
<env name="COLUMNS" value="120"/>
</php> </php>
<testsuites> <testsuites>

View File

@ -6,6 +6,10 @@
failOnRisky="true" failOnRisky="true"
bootstrap="../Doctrine/Tests/TestInit.php" bootstrap="../Doctrine/Tests/TestInit.php"
> >
<php>
<env name="COLUMNS" value="120"/>
</php>
<testsuites> <testsuites>
<testsuite name="Doctrine ORM Test Suite"> <testsuite name="Doctrine ORM Test Suite">
<directory>./../Doctrine/Tests/ORM</directory> <directory>./../Doctrine/Tests/ORM</directory>