diff --git a/lib/Doctrine/ORM/Configuration.php b/lib/Doctrine/ORM/Configuration.php index b52542d05..3cab77ad0 100644 --- a/lib/Doctrine/ORM/Configuration.php +++ b/lib/Doctrine/ORM/Configuration.php @@ -21,8 +21,6 @@ namespace Doctrine\ORM; -use Doctrine\Common\DoctrineException; - /** * Configuration container for all configuration options of Doctrine. * It combines all configuration options from DBAL & ORM. @@ -52,7 +50,7 @@ class Configuration extends \Doctrine\DBAL\Configuration 'namedNativeQueries' => array(), 'autoGenerateProxyClasses' => true, 'proxyNamespace' => null, - 'entityAliasMap' => array() + 'entityNamespaces' => array() )); } @@ -121,24 +119,30 @@ class Configuration extends \Doctrine\DBAL\Configuration } /** - * Add an alias for an entity. + * Add a namespace alias for entities. * - * @param string $className * @param string $alias + * @param string $namespace */ - public function addEntityAlias($className, $alias) + public function addEntityNamespace($alias, $namespace) { - $this->_attributes['entityAliasMap'][$alias] = $className; + $this->_attributes['entityNamespaces'][$alias] = $namespace; } /** - * get the array of entity aliases + * Get the namespace of a given entity namespace * - * @return array $aliasMap + * @param string $entityNamespaceAlias + * @return string + * @throws MappingException */ - public function getEntityAliasMap() + public function getEntityNamespace($entityNamespaceAlias) { - return $this->_attributes['entityAliasMap']; + if (isset($this->_attributes['entityNamespaces'][$entityNamespaceAlias])) { + return trim($this->_attributes['entityNamespaces'][$entityNamespaceAlias], '\\'); + } + + throw ORMException::unknownEntityNamespace($entityNamespaceAlias); } /** @@ -147,9 +151,9 @@ class Configuration extends \Doctrine\DBAL\Configuration * @param array $entityAliasMap * @return void */ - public function setEntityAliasMap(array $entityAliasMap) + public function setEntityNamespaces(array $entityNamespaces) { - $this->_attributes['entityAliasMap'] = $entityAliasMap; + $this->_attributes['entityNamespaces'] = $entityNamespaces; } /** @@ -306,13 +310,13 @@ class Configuration extends \Doctrine\DBAL\Configuration public function ensureProductionSettings() { if ( ! $this->_attributes['queryCacheImpl']) { - throw DoctrineException::queryCacheNotConfigured(); + throw ORMException::queryCacheNotConfigured(); } if ( ! $this->_attributes['metadataCacheImpl']) { - throw DoctrineException::metadataCacheNotConfigured(); + throw ORMException::metadataCacheNotConfigured(); } if ($this->_attributes['autoGenerateProxyClasses']) { - throw DoctrineException::proxyClassesAlwaysRegenerating(); + throw ORMException::proxyClassesAlwaysRegenerating(); } } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index 5bb495c73..dd1d8d8e7 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -128,27 +128,44 @@ class ClassMetadataFactory public function getMetadataFor($className) { if ( ! isset($this->_loadedMetadata[$className])) { - $aliasMap = $this->_em->getConfiguration()->getEntityAliasMap(); - if (isset($aliasMap[$className])) { - $className = $aliasMap[$className]; + $realClassName = $className; + + if (strpos($className, ':') !== false) { + list($namespaceAlias, $simpleClassName) = explode(':', $className); + $realClassName = $this->_em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName; + + if (isset($this->_loadedMetadata[$realClassName])) { + // We do not have the alias reference, include it + $this->_loadedMetadata[$className] = $this->_loadedMetadata[$realClassName]; + + return $this->_loadedMetadata[$realClassName]; + } } - $cacheKey = "$className\$CLASSMETADATA"; + + $cacheKey = "$realClassName\$CLASSMETADATA"; + if ($this->_cacheDriver) { if (($cached = $this->_cacheDriver->fetch($cacheKey)) !== false) { - $this->_loadedMetadata[$className] = $cached; + $this->_loadedMetadata[$realClassName] = $cached; } else { - foreach ($this->_loadMetadata($className) as $loadedClassName) { - $this->_cacheDriver->save($cacheKey, $this->_loadedMetadata[$className], null); + foreach ($this->_loadMetadata($realClassName) as $loadedClassName) { + $this->_cacheDriver->save($cacheKey, $this->_loadedMetadata[$realClassName], null); } } } else { - $this->_loadMetadata($className); + $this->_loadMetadata($realClassName); + } + + // Include the alias of this situation: + // CMS:CmsUser => Doctrine\Tests\ORM\Models\CMS\CmsUser + if ($className != $realClassName) { + $this->_loadedMetadata[$className] = $this->_loadedMetadata[$realClassName]; } } - + return $this->_loadedMetadata[$className]; } - + /** * Checks whether the factory has the metadata for a class loaded already. * diff --git a/lib/Doctrine/ORM/ORMException.php b/lib/Doctrine/ORM/ORMException.php index 0342f1546..7f8150eda 100644 --- a/lib/Doctrine/ORM/ORMException.php +++ b/lib/Doctrine/ORM/ORMException.php @@ -57,14 +57,38 @@ class ORMException extends \Exception return new self("Cannot use different EventManager instances for EntityManager and Connection."); } - public static function findByRequiresParameter($methodName) { + public static function findByRequiresParameter($methodName) + { return new self("You need to pass a parameter to '".$methodName."'"); } - public static function invalidFindByCall($entityName, $fieldName, $method) { + public static function invalidFindByCall($entityName, $fieldName, $method) + { return new self( "Entity '".$entityName."' has no field '".$fieldName."'. ". "You can therefore not call '".$method."' on the entities' repository" ); } + + public static function queryCacheNotConfigured() + { + return new self('Query Cache is not configured.'); + } + + public static function metadataCacheNotConfigured() + { + return new self('Class Metadata Cache is not configured.'); + } + + public static function proxyClassesAlwaysRegenerating() + { + return new self('Proxy Classes are always regenerating.'); + } + + public static function unknownEntityNamespace($entityNamespaceAlias) + { + return new self( + "Unknown Entity namespace alias '$entityNamespaceAlias'." + ); + } } diff --git a/lib/Doctrine/ORM/Query/Lexer.php b/lib/Doctrine/ORM/Query/Lexer.php index b956291d5..79a8dfd39 100644 --- a/lib/Doctrine/ORM/Query/Lexer.php +++ b/lib/Doctrine/ORM/Query/Lexer.php @@ -123,7 +123,7 @@ class Lexer extends \Doctrine\Common\Lexer protected function getCatchablePatterns() { return array( - '[a-z_][a-z0-9_\\\]*', + '[a-z_][a-z0-9_\:\\\]*[a-z0-9_]{1}', '(?:[0-9]+(?:[,\.][0-9]+)*)(?:e[+-]?[0-9]+)?', "'(?:[^']|'')*'", '\?[1-9]+|:[a-z][a-z0-9_]+' diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index eae389828..acc87e548 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -867,12 +867,14 @@ class Parser $this->match(Lexer::T_IDENTIFIER); $schemaName = $this->_lexer->token['value']; - $aliasMap = $this->_em->getConfiguration()->getEntityAliasMap(); - if (isset($aliasMap[$schemaName])) { - $schemaName = $aliasMap[$schemaName]; + + if (strrpos($schemaName, ':') !== false) { + list($namespaceAlias, $simpleClassName) = explode(':', $schemaName); + $schemaName = $this->_em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName; } + $exists = class_exists($schemaName, true); - + if ( ! $exists) { $this->semanticalError("Class '$schemaName' is not defined.", $this->_lexer->token); } diff --git a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php index f72de006c..856c7b8d2 100644 --- a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php @@ -65,6 +65,17 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase $users = $repos->findAll(); $this->assertEquals(2, count($users)); + + $this->_em->clear(); + + $this->_em->getConfiguration()->addEntityNamespace('CMS', 'Doctrine\Tests\Models\CMS'); + + $repos = $this->_em->getRepository('CMS:CmsUser'); + + $users = $repos->findAll(); + $this->assertEquals(2, count($users)); + + $this->_em->getConfiguration()->setEntityNamespaces(array()); } /** diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php index 0cc8ce003..e02c3e44d 100644 --- a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php @@ -227,18 +227,18 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase ->getSingleResult(); } - public function testSupportsQueriesWithEntityAliases() + public function testSupportsQueriesWithEntityNamespaces() { - $this->_em->getConfiguration()->addEntityAlias('Doctrine\Tests\Models\CMS\CmsUser', 'TestAlias'); + $this->_em->getConfiguration()->addEntityNamespace('CMS', 'Doctrine\Tests\Models\CMS'); try { - $query = $this->_em->createQuery('UPDATE TestAlias u SET u.name = ?1'); + $query = $this->_em->createQuery('UPDATE CMS:CmsUser u SET u.name = ?1'); $this->assertEquals('UPDATE cms_users SET name = ?', $query->getSql()); $query->free(); } catch (\Exception $e) { $this->fail($e->getMessage()); } - $this->_em->getConfiguration()->setEntityAliasMap(array()); + $this->_em->getConfiguration()->setEntityNamespaces(array()); } } \ No newline at end of file