diff --git a/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php index 975bc693839..c6c13991427 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php @@ -73,6 +73,8 @@ protected function execute(InputInterface $input, OutputInterface $output) $metadatas = $em->getMetadataFactory()->getAllMetadata(); $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); + $repositoryName = $em->getConfiguration()->getDefaultRepositoryClassName(); + // Process destination directory $destPath = realpath($input->getArgument('dest-path')); @@ -92,6 +94,8 @@ protected function execute(InputInterface $input, OutputInterface $output) $numRepositories = 0; $generator = new EntityRepositoryGenerator(); + $generator->setDefaultRepositoryName($repositoryName); + foreach ($metadatas as $metadata) { if ($metadata->customRepositoryClassName) { $output->writeln( diff --git a/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php b/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php index 5093cd54d5f..f94292afc01 100644 --- a/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php +++ b/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php @@ -32,20 +32,20 @@ */ class EntityRepositoryGenerator { + private $repositoryName; + protected static $_template = ' -use Doctrine\ORM\EntityRepository; - /** * * * This class was generated by the Doctrine ORM. Add your own custom * repository methods below. */ -class extends EntityRepository +class extends { } '; @@ -57,16 +57,49 @@ class extends EntityRepository */ public function generateEntityRepositoryClass($fullClassName) { - $className = substr($fullClassName, strrpos($fullClassName, '\\') + 1, strlen($fullClassName)); - $variables = array( - '' => $this->generateEntityRepositoryNamespace($fullClassName), - '' => $className + '' => $this->generateEntityRepositoryNamespace($fullClassName), + '' => $this->generateEntityRepositoryName($fullClassName), + '' => $this->generateClassName($fullClassName) ); return str_replace(array_keys($variables), array_values($variables), self::$_template); } + /** + * Generates the namespace, if class do not have namespace, return empty string instead. + * + * @param string $fullClassName + * + * @return string $namespace + */ + private function getClassNamespace($fullClassName) + { + $namespace = substr($fullClassName, 0, strrpos($fullClassName, '\\')); + + return $namespace; + } + + /** + * Generates the class name + * + * @param string $fullClassName + * + * @return string + */ + private function generateClassName($fullClassName) + { + $namespace = $this->getClassNamespace($fullClassName); + + $className = $fullClassName; + + if ($namespace) { + $className = substr($fullClassName, strrpos($fullClassName, '\\') + 1, strlen($fullClassName)); + } + + return $className; + } + /** * Generates the namespace statement, if class do not have namespace, return empty string instead. * @@ -76,11 +109,29 @@ public function generateEntityRepositoryClass($fullClassName) */ private function generateEntityRepositoryNamespace($fullClassName) { - $namespace = substr($fullClassName, 0, strrpos($fullClassName, '\\')); - + $namespace = $this->getClassNamespace($fullClassName); + return $namespace ? 'namespace ' . $namespace . ';' : ''; } + /** + * @param string $fullClassName + * + * @return string $repositoryName + */ + private function generateEntityRepositoryName($fullClassName) + { + $namespace = $this->getClassNamespace($fullClassName); + + $repositoryName = $this->repositoryName ?: 'Doctrine\ORM\EntityRepository'; + + if ($namespace && $repositoryName[0] !== '\\') { + $repositoryName = '\\' . $repositoryName; + } + + return $repositoryName; + } + /** * @param string $fullClassName * @param string $outputDirectory @@ -103,4 +154,17 @@ public function writeEntityRepositoryClass($fullClassName, $outputDirectory) file_put_contents($path, $code); } } + + /** + * @param string $repositoryName + * + * @return \Doctrine\ORM\Tools\EntityRepositoryGenerator + */ + public function setDefaultRepositoryName($repositoryName) + { + $this->repositoryName = $repositoryName; + + return $this; + } + } diff --git a/tests/Doctrine/Tests/Models/DDC3231/DDC3231EntityRepository.php b/tests/Doctrine/Tests/Models/DDC3231/DDC3231EntityRepository.php new file mode 100644 index 00000000000..91ca8453c9d --- /dev/null +++ b/tests/Doctrine/Tests/Models/DDC3231/DDC3231EntityRepository.php @@ -0,0 +1,7 @@ +path = \sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('doctrine_'); + + \mkdir($this->path); + + + $metadataDriver = $this->_em->getConfiguration()->getMetadataDriverImpl(); + + $metadataDriver->addPaths(array( + __DIR__ . '/../../../../Models/DDC3231/' + )); + + $this->application = new Application(); + + $this->application->setHelperSet(new HelperSet(array( + 'em' => new EntityManagerHelper($this->_em) + ))); + + $this->application->add(new GenerateRepositoriesCommand()); + + } + + /** + * @inheritdoc + */ + public function tearDown() + { + $dirs = array(); + + $ri = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->path)); + foreach ($ri AS $file) { + /* @var $file \SplFileInfo */ + if ($file->isFile()) { + \unlink($file->getPathname()); + } elseif ($file->getBasename() === '.') { + $dirs[] = $file->getRealpath(); + } + } + + arsort($dirs); + + foreach ($dirs as $dir) { + \rmdir($dir); + } + + parent::tearDown(); + } + + public function testGenerateRepositories() + { + $this->generateRepositories('DDC3231User1'); + + $cname = 'Doctrine\Tests\Models\DDC3231\DDC3231User1Repository'; + $fname = str_replace('\\', DIRECTORY_SEPARATOR, $cname) . '.php'; + + $this->assertFileExists($this->path . DIRECTORY_SEPARATOR . $fname); + $this->assertFileExists($this->path . DIRECTORY_SEPARATOR . 'DDC3231User1NoNamespaceRepository.php'); + + require $this->path . DIRECTORY_SEPARATOR . $fname; + require $this->path . DIRECTORY_SEPARATOR . 'DDC3231User1NoNamespaceRepository.php'; + + $this->assertTrue(class_exists($cname)); + $this->assertTrue(class_exists('DDC3231User1NoNamespaceRepository')); + + $repo1 = new \ReflectionClass($cname); + $repo2 = new \ReflectionClass('DDC3231User1NoNamespaceRepository'); + + $this->assertSame('Doctrine\ORM\EntityRepository', $repo1->getParentClass()->getName()); + $this->assertSame('Doctrine\ORM\EntityRepository', $repo2->getParentClass()->getName()); + } + + public function testGenerateRepositoriesCustomDefaultRepository() + { + $this->generateRepositories('DDC3231User2', 'Doctrine\Tests\Models\DDC3231\DDC3231EntityRepository'); + + $cname = 'Doctrine\Tests\Models\DDC3231\DDC3231User2Repository'; + $fname = str_replace('\\', DIRECTORY_SEPARATOR, $cname) . '.php'; + + $this->assertFileExists($this->path . DIRECTORY_SEPARATOR . $fname); + $this->assertFileExists($this->path . DIRECTORY_SEPARATOR . 'DDC3231User2NoNamespaceRepository.php'); + + require $this->path . DIRECTORY_SEPARATOR . $fname; + require $this->path . DIRECTORY_SEPARATOR . 'DDC3231User2NoNamespaceRepository.php'; + + $this->assertTrue(class_exists($cname)); + $this->assertTrue(class_exists('DDC3231User2NoNamespaceRepository')); + + $repo1 = new \ReflectionClass($cname); + $repo2 = new \ReflectionClass('DDC3231User2NoNamespaceRepository'); + + $this->assertSame('Doctrine\Tests\Models\DDC3231\DDC3231EntityRepository', $repo1->getParentClass()->getName()); + $this->assertSame('Doctrine\Tests\Models\DDC3231\DDC3231EntityRepository', $repo2->getParentClass()->getName()); + } + + /** + * @param string $filter + * @param string $defaultRepository + */ + private function generateRepositories($filter, $defaultRepository = null) + { + if ($defaultRepository) { + $this->_em->getConfiguration()->setDefaultRepositoryClassName($defaultRepository); + } + + $command = $this->application->find('orm:generate-repositories'); + $tester = new CommandTester($command); + $tester->execute(array( + 'command' => $command->getName(), + 'dest-path' => $this->path, + '--filter' => $filter, + )); + } + +} diff --git a/tests/Doctrine/Tests/ORM/Tools/EntityRepositoryGeneratorTest.php b/tests/Doctrine/Tests/ORM/Tools/EntityRepositoryGeneratorTest.php new file mode 100644 index 00000000000..02d6ed5a13a --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Tools/EntityRepositoryGeneratorTest.php @@ -0,0 +1,196 @@ +_namespace = uniqid('doctrine_'); + $this->_tmpDir = \sys_get_temp_dir() . DIRECTORY_SEPARATOR . $this->_namespace; + \mkdir($this->_tmpDir); + + $this->_generator = new EntityGenerator(); + $this->_generator->setAnnotationPrefix(""); + $this->_generator->setGenerateAnnotations(true); + $this->_generator->setGenerateStubMethods(true); + $this->_generator->setRegenerateEntityIfExists(false); + $this->_generator->setUpdateEntityIfExists(true); + $this->_generator->setFieldVisibility(EntityGenerator::FIELD_VISIBLE_PROTECTED); + + $this->_repositoryGenerator = new EntityRepositoryGenerator(); + } + + /** + * @inheritdoc + */ + public function tearDown() + { + $dirs = array(); + + $ri = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->_tmpDir)); + foreach ($ri AS $file) { + /* @var $file \SplFileInfo */ + if ($file->isFile()) { + \unlink($file->getPathname()); + } elseif ($file->getBasename() === '.') { + $dirs[] = $file->getRealpath(); + } + } + + arsort($dirs); + + foreach ($dirs as $dir) { + \rmdir($dir); + } + } + + /** + * @group DDC-3231 + */ + public function testGeneratedEntityRepositoryClass() + { + $em = $this->_getTestEntityManager(); + $ns = $this->_namespace; + + + require_once __DIR__ . '/../../Models/DDC3231/DDC3231User1.php'; + + $className = $ns . '\DDC3231User1Tmp'; + $this->writeEntityClass('Doctrine\Tests\Models\DDC3231\DDC3231User1', $className); + + $rpath = $this->writeRepositoryClass($className); + + $this->assertFileExists($rpath); + + require $rpath; + + $repo = new \ReflectionClass($em->getRepository($className)); + + $this->assertTrue($repo->inNamespace()); + $this->assertSame($className . 'Repository', $repo->getName()); + $this->assertSame('Doctrine\ORM\EntityRepository', $repo->getParentClass()->getName()); + + + require_once __DIR__ . '/../../Models/DDC3231/DDC3231User1NoNamespace.php'; + + $className2 = 'DDC3231User1NoNamespaceTmp'; + $this->writeEntityClass('DDC3231User1NoNamespace', $className2); + + $rpath2 = $this->writeRepositoryClass($className2); + + $this->assertFileExists($rpath2); + + require $rpath2; + + $repo2 = new \ReflectionClass($em->getRepository($className2)); + + $this->assertFalse($repo2->inNamespace()); + $this->assertSame($className2 . 'Repository', $repo2->getName()); + $this->assertSame('Doctrine\ORM\EntityRepository', $repo2->getParentClass()->getName()); + } + + /** + * @group DDC-3231 + */ + public function testGeneratedEntityRepositoryClassCustomDefaultRepository() + { + $em = $this->_getTestEntityManager(); + $ns = $this->_namespace; + + + require_once __DIR__ . '/../../Models/DDC3231/DDC3231User2.php'; + + $className = $ns . '\DDC3231User2Tmp'; + $this->writeEntityClass('Doctrine\Tests\Models\DDC3231\DDC3231User2', $className); + + $rpath = $this->writeRepositoryClass($className, 'Doctrine\Tests\Models\DDC3231\DDC3231EntityRepository'); + + $this->assertNotNull($rpath); + $this->assertFileExists($rpath); + + require $rpath; + + $repo = new \ReflectionClass($em->getRepository($className)); + + $this->assertTrue($repo->inNamespace()); + $this->assertSame($className . 'Repository', $repo->getName()); + $this->assertSame('Doctrine\Tests\Models\DDC3231\DDC3231EntityRepository', $repo->getParentClass()->getName()); + + + require_once __DIR__ . '/../../Models/DDC3231/DDC3231User2NoNamespace.php'; + + $className2 = 'DDC3231User2NoNamespaceTmp'; + $this->writeEntityClass('DDC3231User2NoNamespace', $className2); + + $rpath2 = $this->writeRepositoryClass($className2, 'Doctrine\Tests\Models\DDC3231\DDC3231EntityRepository'); + + $this->assertNotNull($rpath2); + $this->assertFileExists($rpath2); + + require $rpath2; + + $repo2 = new \ReflectionClass($em->getRepository($className2)); + + $this->assertFalse($repo2->inNamespace()); + $this->assertSame($className2 . 'Repository', $repo2->getName()); + $this->assertSame('Doctrine\Tests\Models\DDC3231\DDC3231EntityRepository', $repo2->getParentClass()->getName()); + } + + /** + * @param string $className + * @param string $newClassName + * @return string + */ + private function writeEntityClass($className, $newClassName) + { + $cmf = new ClassMetadataFactory(); + $em = $this->_getTestEntityManager(); + + $cmf->setEntityManager($em); + + $metadata = $cmf->getMetadataFor($className); + $metadata->namespace = $this->_namespace; + $metadata->name = $newClassName; + $metadata->customRepositoryClassName = $newClassName . "Repository"; + + $this->_generator->writeEntityClass($metadata, $this->_tmpDir); + + require $this->_tmpDir . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $newClassName) . ".php"; + } + + /** + * @param string $className + * @param string $defaultRepository + * @return string + */ + private function writeRepositoryClass($className, $defaultRepository = null) + { + $this->_repositoryGenerator->setDefaultRepositoryName($defaultRepository); + + $this->_repositoryGenerator->writeEntityRepositoryClass($className . 'Repository', $this->_tmpDir); + + return $this->_tmpDir . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $className) . 'Repository.php'; + } + +}