diff --git a/UPDATE.md b/UPDATE.md index 125638b90a..b8b84fe55b 100644 --- a/UPDATE.md +++ b/UPDATE.md @@ -9,6 +9,13 @@ timeline closely anyway. beta1 to beta2 -------------- +* The `doctrine:generate:entities` arguments and options changed. Run + `./app/console doctrine:generate:entities --help` for more information about + the new syntax. + +* The `doctrine:generate:repositories` command has been removed. The + functionality has been moved to the `doctrine:generate:entities`. + * Doctrine event subscribers now use a unique "doctrine.event_subscriber" tag. Doctrine event listeners also use a unique "doctrine.event_listener" tag. To specify a connection, use the optional "connection" attribute. diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php index 09acbc12e1..f0e9dbde55 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php +++ b/src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php @@ -17,6 +17,8 @@ use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Tools\EntityGenerator; +use Doctrine\ORM\Version as DoctrineVersion; +use Doctrine\ORM\ORMException; /** * Base class for Doctrine console commands to extend from. @@ -29,7 +31,7 @@ abstract class DoctrineCommand extends Command { $entityGenerator = new EntityGenerator(); - if (version_compare(\Doctrine\ORM\Version::VERSION, "2.0.2-DEV") >= 0) { + if (version_compare(DoctrineVersion::VERSION, "2.0.2-DEV") >= 0) { $entityGenerator->setAnnotationPrefix("orm:"); } $entityGenerator->setGenerateAnnotations(false); @@ -37,6 +39,7 @@ abstract class DoctrineCommand extends Command $entityGenerator->setRegenerateEntityIfExists(false); $entityGenerator->setUpdateEntityIfExists(true); $entityGenerator->setNumSpaces(4); + return $entityGenerator; } @@ -70,23 +73,41 @@ abstract class DoctrineCommand extends Command return $this->container->get($connections[$name]); } - protected function getBundleMetadatas(Bundle $bundle) + protected function findMetadatasByNamespace($namespace) { - $namespace = $bundle->getNamespace(); - $bundleMetadatas = array(); - foreach ($this->container->getParameter('doctrine.orm.entity_managers') as $id) { - $em = $this->container->get($id); - $cmf = new DisconnectedClassMetadataFactory(); - $cmf->setEntityManager($em); - $metadatas = $cmf->getAllMetadata(); - foreach ($metadatas as $metadata) { - if (strpos($metadata->name, $namespace) === 0) { - $bundleMetadatas[$metadata->name] = $metadata; - } + $metadatas = array(); + foreach ($this->findAllMetadatas() as $name => $metadata) { + if (strpos($name, $namespace) === 0) { + $metadatas[$name] = $metadata; } } - return $bundleMetadatas; + return $metadatas; + } + + protected function findMetadatasByClass($entity) + { + foreach ($this->findAllMetadatas() as $name => $metadata) { + if ($name === $entity) { + return array($name => $metadata); + } + } + + return array(); + } + + protected function findAllMetadatas() + { + $metadatas = array(); + foreach ($this->container->getParameter('doctrine.orm.entity_managers') as $id) { + $cmf = new DisconnectedClassMetadataFactory(); + $cmf->setEntityManager($this->container->get($id)); + foreach ($cmf->getAllMetadata() as $metadata) { + $metadatas[$metadata->name] = $metadata; + } + } + + return $metadatas; } /** @@ -95,16 +116,33 @@ abstract class DoctrineCommand extends Command * @param Bundle $bundle * @return string */ - protected function findBasePathForBundle($bundle) + protected function findBasePathForClass($name, $namespace, $path) { - $path = str_replace('\\', '/', $bundle->getNamespace()); - $search = str_replace('\\', '/', $bundle->getPath()); - $destination = str_replace('/'.$path, '', $search, $c); + $namespace = str_replace('\\', '/', $namespace); + $search = str_replace('\\', '/', $path); + $destination = str_replace('/'.$namespace, '', $search, $c); if ($c != 1) { - throw new \RuntimeException(sprintf('Can\'t find base path for bundle (path: "%s", destination: "%s").', $path, $destination)); + throw new \RuntimeException(sprintf('Can\'t find base path for "%s" (path: "%s", destination: "%s").', $name, $path, $destination)); } return $destination; } + + protected function getAliasedClassName($name) + { + $pos = strpos($name, ':'); + $alias = substr($name, 0, $pos); + + foreach ($this->container->getParameter('doctrine.orm.entity_managers') as $id) { + $em = $this->container->get($id); + + try { + return $em->getConfiguration()->getEntityNamespace($alias).'\\'.substr($name, $pos + 1); + } catch (ORMException $e) { + } + } + + throw new \RuntimeException(sprintf('Entity "%s" does not exist.', $name)); + } } diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php index 9fd144eae7..f906b1d510 100644 --- a/src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php +++ b/src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php @@ -29,51 +29,107 @@ class GenerateEntitiesDoctrineCommand extends DoctrineCommand $this ->setName('doctrine:generate:entities') ->setDescription('Generate entity classes and method stubs from your mapping information') - ->addArgument('bundle', InputArgument::REQUIRED, 'The bundle to initialize the entity or entities in') - ->addOption('entity', null, InputOption::VALUE_OPTIONAL, 'The entity class to initialize (shortname without namespace)') + ->addArgument('name', InputArgument::REQUIRED, 'A bundle name, a namespace, or a class name') ->setHelp(<<doctrine:generate:entities command generates entity classes and method stubs from your mapping information: -You have to limit generation of entities to an individual bundle: +You have to limit generation of entities: -./app/console doctrine:generate:entities MyCustomBundle +* To a bundle: -Alternatively, you can limit generation to a single entity within a bundle: + ./app/console doctrine:generate:entities MyCustomBundle -./app/console doctrine:generate:entities "MyCustomBundle" --entity="User" +* To a single entity: -You have to specify the shortname (without namespace) of the entity you want -to filter for. + ./app/console doctrine:generate:entities MyCustomBundle:User + ./app/console doctrine:generate:entities MyCustomBundle/Entity/User + +* To a namespace + + ./app/console doctrine:generate:entities MyCustomBundle/Entity EOT ); } protected function execute(InputInterface $input, OutputInterface $output) { - $bundleName = $input->getArgument('bundle'); - $filterEntity = $input->getOption('entity'); + try { + $bundle = $this->getApplication()->getKernel()->getBundle($input->getArgument('name')); - $foundBundle = $this->getApplication()->getKernel()->getBundle($bundleName); + $output->writeln(sprintf('Generating entities for bundle "%s"', $bundle->getName())); + list($metadatas, $path) = $this->getBundleInfo($bundle); + } catch (\InvalidArgumentException $e) { + $name = strtr($input->getArgument('name'), '/', '\\'); - if ($metadatas = $this->getBundleMetadatas($foundBundle)) { - $output->writeln(sprintf('Generating entities for "%s"', $foundBundle->getName())); - $entityGenerator = $this->getEntityGenerator(); - - foreach ($metadatas as $metadata) { - if ($filterEntity && $metadata->getReflectionClass()->getShortName() !== $filterEntity) { - continue; - } - - if (strpos($metadata->name, $foundBundle->getNamespace()) === false) { - throw new \RuntimeException(sprintf('Entity "%s" and bundle don\'t have a common namespace, generation failed because the target directory cannot be detected.', $metadata->name)); - } - - $output->writeln(sprintf(' > generating %s', $metadata->name)); - $entityGenerator->generate(array($metadata), $this->findBasePathForBundle($foundBundle)); + if (false !== strpos($name, ':')) { + $name = $this->getAliasedClassName($name); + } + + if (class_exists($name)) { + $output->writeln(sprintf('Generating entity "%s"', $name)); + list($metadatas, $path) = $this->getClassInfo($name); + } else { + $output->writeln(sprintf('Generating entities for namespace "%s"', $name)); + list($metadatas, $path) = $this->getNamespaceInfo($name); + } + } + + $generator = $this->getEntityGenerator(); + foreach ($metadatas as $metadata) { + $output->writeln(sprintf(' > generating %s', $metadata->name)); + $generator->generate(array($metadata), $path); + + if ($metadata->customRepositoryClassName) { + if (false === strpos($metadata->customRepositoryClassName, $namespace)) { + continue + } + + $generator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $path); } - } else { - throw new \RuntimeException(sprintf('Bundle "%s" does not contain any mapped entities.', $bundleName)); } } + + private function getBundleInfo($bundle) + { + $namespace = $bundle->getNamespace(); + if (!$metadatas = $this->findMetadatasByNamespace($namespace)) { + throw new \RuntimeException(sprintf('Bundle "%s" does not contain any mapped entities.', $bundle->getName())); + } + + $path = $this->findBasePathForClass($bundle->getName(), $bundle->getNamespace(), $bundle->getPath()); + + return array($metadatas, $path); + } + + private function getClassInfo($class) + { + if (!$metadatas = $this->findMetadatasByClass($class)) { + throw new \RuntimeException(sprintf('Entity "%s" is not a mapped entity.', $class)); + } + + $r = $metadatas[$class]->getReflectionClass(); + if (!$r) { + throw new \RuntimeException('Unable to determine where to save the "%s" class.', $class); + } + $path = $this->findBasePathForClass($class, $r->getNamespacename(), dirname($r->getFilename())); + + return array($metadatas, $path); + } + + private function getNamespaceInfo($namespace) + { + if (!$metadatas = $this->findMetadatasByNamespace($namespace)) { + throw new \RuntimeException(sprintf('Namespace "%s" does not contain any mapped entities.', $namespace)); + } + + $first = reset($metadatas); + $r = $first->getReflectionClass(); + if (!$r) { + throw new \RuntimeException('Unable to determine where to save the "%s" class.', $class); + } + $path = $this->findBasePathForClass($namespace, $r->getNamespacename(), dirname($r->getFilename())); + + return array($metadatas, $path); + } } diff --git a/src/Symfony/Bundle/DoctrineBundle/Command/GenerateRepositoriesDoctrineCommand.php b/src/Symfony/Bundle/DoctrineBundle/Command/GenerateRepositoriesDoctrineCommand.php deleted file mode 100644 index 3fcde650b6..0000000000 --- a/src/Symfony/Bundle/DoctrineBundle/Command/GenerateRepositoriesDoctrineCommand.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\DoctrineBundle\Command; - -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Doctrine\ORM\Tools\EntityRepositoryGenerator; - -/** - * Command to generate repository classes for mapping information. - * - * @author Fabien Potencier - * @author Jonathan H. Wage - */ -class GenerateRepositoriesDoctrineCommand extends DoctrineCommand -{ - protected function configure() - { - $this - ->setName('doctrine:generate:repositories') - ->setDescription('Generate repository classes from your mapping information') - ->addArgument('bundle', InputArgument::REQUIRED, 'The bundle to initialize the repositories in') - ->addOption('entity', null, InputOption::VALUE_OPTIONAL, 'The entity class to generate the repository for (shortname without namespace)') - ->setHelp(<<doctrine:generate:repositories command generates the -configured entity repository classes from your mapping information: - -./app/console doctrine:generate:repositories -EOT - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $bundleName = $input->getArgument('bundle'); - $filterEntity = $input->getOption('entity'); - - $foundBundle = $this->getApplication()->getKernel()->getBundle($bundleName); - - if ($metadatas = $this->getBundleMetadatas($foundBundle)) { - $output->writeln(sprintf('Generating entity repositories for "%s"', $foundBundle->getName())); - $generator = new EntityRepositoryGenerator(); - - foreach ($metadatas as $metadata) { - if ($filterEntity && $filterEntity !== $metadata->reflClass->getShortname()) { - continue; - } - - if ($metadata->customRepositoryClassName) { - if (strpos($metadata->customRepositoryClassName, $foundBundle->getNamespace()) === false) { - throw new \RuntimeException(sprintf('Repository "%s" and bundle don\'t have a common namespace, generation failed because the target directory cannot be detected.', $metadata->customRepositoryClassName)); - } - - $output->writeln(sprintf(' > OK generating %s', $metadata->customRepositoryClassName)); - $generator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $this->findBasePathForBundle($foundBundle)); - } else { - $output->writeln(sprintf(' > SKIP no custom repository defined for %s (no "repositoryClass" option found in the metadata)', $metadata->name)); - } - } - } else { - throw new \RuntimeException(sprintf('Bundle "%s" does not contain any mapped entities.', $bundleName)); - } - } -}