瀏覽代碼

[DoctrineBundle] extracted code from Doctrine commands

Fabien Potencier 14 年之前
父節點
當前提交
a0462593eb

+ 0 - 79
src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php

@@ -12,13 +12,7 @@
 namespace Symfony\Bundle\DoctrineBundle\Command;
 
 use Symfony\Bundle\FrameworkBundle\Command\Command;
-use Symfony\Component\HttpKernel\Bundle\Bundle;
-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.
@@ -54,77 +48,4 @@ abstract class DoctrineCommand extends Command
     {
         return $this->container->get('doctrine')->getConnection($name);
     }
-
-    protected function findMetadatasByNamespace($namespace)
-    {
-        $metadatas = array();
-        foreach ($this->findAllMetadatas() as $name => $metadata) {
-            if (strpos($name, $namespace) === 0) {
-                $metadatas[$name] = $metadata;
-            }
-        }
-
-        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->get('doctrine')->getEntityManagerNames() as $id) {
-            $cmf = new DisconnectedClassMetadataFactory();
-            $cmf->setEntityManager($this->container->get($id));
-            foreach ($cmf->getAllMetadata() as $metadata) {
-                $metadatas[$metadata->name] = $metadata;
-            }
-        }
-
-        return $metadatas;
-    }
-
-    /**
-     * Transform classname to a path $foundBundle substract it to get the destination
-     *
-     * @param Bundle $bundle
-     * @return string
-     */
-    protected function findBasePathForClass($name, $namespace, $path)
-    {
-        $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 "%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->get('doctrine')->getEntityManagerNames() 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));
-    }
 }

+ 13 - 60
src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php

@@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 use Doctrine\ORM\Tools\EntityRepositoryGenerator;
+use Symfony\Bundle\DoctrineBundle\Mapping\MetadataFactory;
 
 /**
  * Generate entity classes from mapping information
@@ -69,87 +70,39 @@ EOT
 
     protected function execute(InputInterface $input, OutputInterface $output)
     {
+        $manager = new MetadataFactory($this->container->get('doctrine'));
+
         try {
             $bundle = $this->getApplication()->getKernel()->getBundle($input->getArgument('name'));
 
             $output->writeln(sprintf('Generating entities for bundle "<info>%s</info>"', $bundle->getName()));
-            list($metadatas, $namespace, $path) = $this->getBundleInfo($bundle);
+            $metadata = $manager->getBundleMetadata($bundle);
         } catch (\InvalidArgumentException $e) {
             $name = strtr($input->getArgument('name'), '/', '\\');
 
-            if (false !== strpos($name, ':')) {
-                $name = $this->getAliasedClassName($name);
+            if (false !== $pos = strpos($name, ':')) {
+                $name = $this->container->get('doctrine')->getEntityNamespace(substr($name, 0, $pos)).'\\'.substr($name, $pos + 1);
             }
 
             if (class_exists($name)) {
                 $output->writeln(sprintf('Generating entity "<info>%s</info>"', $name));
-                list($metadatas, $namespace, $path) = $this->getClassInfo($name, $input->getOption('path'));
+                $metadata = $manager->getClassMetadata($name, $input->getOption('path'));
             } else {
                 $output->writeln(sprintf('Generating entities for namespace "<info>%s</info>"', $name));
-                list($metadatas, $namespace, $path) = $this->getNamespaceInfo($name, $input->getOption('path'));
+                $metadata = $manager->getNamespaceMetadata($name, $input->getOption('path'));
             }
         }
 
         $generator = $this->getEntityGenerator();
         $generator->setBackupExisting(!$input->getOption('no-backup'));
         $repoGenerator = new EntityRepositoryGenerator();
-        foreach ($metadatas as $metadata) {
-            $output->writeln(sprintf('  > generating <comment>%s</comment>', $metadata->name));
-            $generator->generate(array($metadata), $path);
-
-            if ($metadata->customRepositoryClassName) {
-                if (false === strpos($metadata->customRepositoryClassName, $namespace)) {
-                    continue;
-                }
+        foreach ($metadata->getMetadata() as $m) {
+            $output->writeln(sprintf('  > generating <comment>%s</comment>', $m->name));
+            $generator->generate(array($m), $metadata->getPath());
 
-                $repoGenerator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $path);
+            if ($m->customRepositoryClassName && false !== strpos($m->customRepositoryClassName, $metadata->getNamespace())) {
+                $repoGenerator->writeEntityRepositoryClass($m->customRepositoryClassName, $metadata->getPath());
             }
         }
     }
-
-    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, $bundle->getNamespace(), $path);
-    }
-
-    private function getClassInfo($class, $path)
-    {
-        if (!$metadatas = $this->findMetadatasByClass($class)) {
-            throw new \RuntimeException(sprintf('Entity "%s" is not a mapped entity.', $class));
-        }
-
-        if (class_exists($class)) {
-            $r = $metadatas[$class]->getReflectionClass();
-            $path = $this->findBasePathForClass($class, $r->getNamespacename(), dirname($r->getFilename()));
-        } elseif (!$path) {
-            throw new \RuntimeException(sprintf('Unable to determine where to save the "%s" class (use the --path option).', $class));
-        }
-
-        return array($metadatas, $r->getNamespacename(), $path);
-    }
-
-    private function getNamespaceInfo($namespace, $path)
-    {
-        if (!$metadatas = $this->findMetadatasByNamespace($namespace)) {
-            throw new \RuntimeException(sprintf('Namespace "%s" does not contain any mapped entities.', $namespace));
-        }
-
-        $first = reset($metadatas);
-        $class = key($metadatas);
-        if (class_exists($class)) {
-            $r = $first->getReflectionClass();
-            $path = $this->findBasePathForClass($namespace, $r->getNamespacename(), dirname($r->getFilename()));
-        } elseif (!$path) {
-            throw new \RuntimeException(sprintf('Unable to determine where to save the "%s" class (use the --path option).', $class));
-        }
-
-        return array($metadatas, $namespace, $path);
-    }
 }

+ 54 - 0
src/Symfony/Bundle/DoctrineBundle/Mapping/ClassMetadataCollection.php

@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\DoctrineBundle\Mapping;
+
+/**
+ *
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ClassMetadataCollection
+{
+    private $path;
+    private $namespace;
+    private $metadata;
+
+    public function __construct(array $metadata)
+    {
+        $this->metadata = $metadata;
+    }
+
+    public function getMetadata()
+    {
+        return $this->metadata;
+    }
+
+    public function setPath($path)
+    {
+        $this->path = $path;
+    }
+
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    public function setNamespace($namespace)
+    {
+        $this->namespace = $namespace;
+    }
+
+    public function getNamespace()
+    {
+        return $this->namespace;
+    }
+}

+ 166 - 0
src/Symfony/Bundle/DoctrineBundle/Mapping/MetadataFactory.php

@@ -0,0 +1,166 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\DoctrineBundle\Mapping;
+
+use Symfony\Bundle\DoctrineBundle\Registry;
+use Symfony\Component\HttpKernel\Bundle\BundleInterface;
+use Doctrine\ORM\Tools\EntityRepositoryGenerator;
+use Doctrine\ORM\Mapping\ClassMetadata;
+use Doctrine\ORM\Mapping\ClassMetadataInfo;
+use Doctrine\ORM\ORMException;
+use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
+
+/**
+ *
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class MetadataFactory
+{
+    private $registry;
+
+    /**
+     * Constructor.
+     *
+     * @param Registry $registry A Registry instance
+     */
+    public function __construct(Registry $registry)
+    {
+        $this->registry = $registry;
+    }
+
+    /**
+     * Gets the metadata of all classes of a bundle.
+     *
+     * @param BundleInterface $bundle A BundleInterface instance
+     *
+     * @return ClassMetadataCollection A ClassMetadataCollection instance
+     */
+    public function getBundleMetadata(BundleInterface $bundle)
+    {
+        $namespace = $bundle->getNamespace();
+        if (!$metadata = $this->getMetadataForNamespace($namespace)) {
+            throw new \RuntimeException(sprintf('Bundle "%s" does not contain any mapped entities.', $bundle->getName()));
+        }
+
+        $path = $this->getBasePathForClass($bundle->getName(), $bundle->getNamespace(), $bundle->getPath());
+
+        $metadata->setPath($path);
+        $metadata->setNamespace($bundle->getNamespace());
+
+        return $metadata;
+    }
+
+    /**
+     * Gets the metadata of a class.
+     *
+     * @param string $class A class name
+     * @param string $path  The path where the class is stored (if known)
+     *
+     * @return ClassMetadataCollection A ClassMetadataCollection instance
+     */
+    public function getClassMetadata($class, $path = null)
+    {
+        if (!$metadata = $this->getMetadataForClass($class)) {
+            throw new \RuntimeException(sprintf('Entity "%s" is not a mapped entity.', $class));
+        }
+
+        $all = $metadata->getMetadata();
+        if (class_exists($class)) {
+            $r = $all[0]->getReflectionClass();
+            $path = $this->getBasePathForClass($class, $r->getNamespacename(), dirname($r->getFilename()));
+        } elseif (!$path) {
+            throw new \RuntimeException(sprintf('Unable to determine where to save the "%s" class (use the --path option).', $class));
+        }
+
+        $metadata->setPath($path);
+        $metadata->setNamespace($r->getNamespacename());
+
+        return $metadata;
+    }
+
+    /**
+     * Gets the metadata of all classes of a namespace.
+     *
+     * @param string $namespace A namespace name
+     * @param string $path      The path where the class is stored (if known)
+     *
+     * @return ClassMetadataCollection A ClassMetadataCollection instance
+     */
+    public function getNamespaceMetadata($namespace, $path = null)
+    {
+        if (!$metadata = $this->getMetadataForNamespace($namespace)) {
+            throw new \RuntimeException(sprintf('Namespace "%s" does not contain any mapped entities.', $namespace));
+        }
+
+        $all = $metadata->getMetadata();
+        if (class_exists($all[0]->name)) {
+            $r = $all[0]->getReflectionClass();
+            $path = $this->getBasePathForClass($namespace, $r->getNamespacename(), dirname($r->getFilename()));
+        } elseif (!$path) {
+            throw new \RuntimeException(sprintf('Unable to determine where to save the "%s" class (use the --path option).', $all[0]->name));
+        }
+
+        $metadata->setPath($path);
+        $metadata->setNamespace($namespace);
+
+        return $metadata;
+    }
+
+    private function getBasePathForClass($name, $namespace, $path)
+    {
+        $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 "%s" (path: "%s", destination: "%s").', $name, $path, $destination));
+        }
+
+        return $destination;
+    }
+
+    private function getMetadataForNamespace($namespace)
+    {
+        $metadata = array();
+        foreach ($this->getAllMetadata() as $m) {
+            if (strpos($m->name, $namespace) === 0) {
+                $metadata[] = $m;
+            }
+        }
+
+        return new ClassMetadataCollection($metadata);
+    }
+
+    private function getMetadataForClass($entity)
+    {
+        foreach ($this->getAllMetadata() as $metadata) {
+            if ($metadata->name === $entity) {
+                return new ClassMetadataCollection(array($metadata));
+            }
+        }
+    }
+
+    private function getAllMetadata()
+    {
+        $metadata = array();
+        foreach ($this->registry->getEntityManagerNames() as $name => $id) {
+            $cmf = new DisconnectedClassMetadataFactory();
+            $cmf->setEntityManager($this->registry->getEntityManager($name));
+            foreach ($cmf->getAllMetadata() as $m) {
+                $metadata[] = $m;
+            }
+        }
+
+        return $metadata;
+    }
+}

+ 25 - 0
src/Symfony/Bundle/DoctrineBundle/Registry.php

@@ -13,6 +13,8 @@ namespace Symfony\Bundle\DoctrineBundle;
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Doctrine\DBAL\Connection;
+use Doctrine\ORM\Configuration;
+use Doctrine\ORM\ORMException;
 
 /**
  * References all Doctrine connections and entity managers in a given Container.
@@ -138,6 +140,29 @@ class Registry
         $this->container->set($this->entityManagers[$name], null);
     }
 
+    /**
+     * Resolves a registered namespace alias to the full namespace.
+     *
+     * This method looks for the alias in all registered entity managers.
+     *
+     * @param string $alias The alias
+     *
+     * @return string The full namespace
+     *
+     * @see Configuration::getEntityNamespace
+     */
+    public function getEntityNamespace($alias)
+    {
+        foreach (array_keys($this->entityManagers) as $name) {
+            try {
+                return $this->getEntityManager($name)->getConfiguration()->getEntityNamespace($alias);
+            } catch (ORMException $e) {
+            }
+        }
+
+        throw ORMException::unknownEntityNamespace($alias);
+    }
+
     /**
      * Gets all connection names.
      *