diff --git a/composer.json b/composer.json index 8f00b5236..a216eb192 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "ext-pdo": "*", "doctrine/collections": "~1.2", "doctrine/dbal": ">=2.5-dev,<2.6-dev", + "doctrine/instantiator": "~1.0.1", "symfony/console": "2.*" }, "require-dev": { diff --git a/docs/en/reference/batch-processing.rst b/docs/en/reference/batch-processing.rst index 26f16ffd3..5d3cf1887 100644 --- a/docs/en/reference/batch-processing.rst +++ b/docs/en/reference/batch-processing.rst @@ -42,6 +42,8 @@ internally but also mean more work during ``flush``. $em->clear(); // Detaches all objects from Doctrine! } } + $em->flush(); //Persist objects that did not make up an entire batch + $em->clear(); Bulk Updates ------------ diff --git a/docs/en/reference/caching.rst b/docs/en/reference/caching.rst index ff5cadd7b..0f18e8a20 100644 --- a/docs/en/reference/caching.rst +++ b/docs/en/reference/caching.rst @@ -4,9 +4,9 @@ Caching Doctrine provides cache drivers in the ``Common`` package for some of the most popular caching implementations such as APC, Memcache and Xcache. We also provide an ``ArrayCache`` driver which stores -the data in a PHP array. Obviously, the cache does not live between -requests but this is useful for testing in a development -environment. +the data in a PHP array. Obviously, when using ``ArrayCache``, the +cache does not persist between requests, but this is useful for +testing in a development environment. Cache Drivers ------------- @@ -14,20 +14,19 @@ Cache Drivers The cache drivers follow a simple interface that is defined in ``Doctrine\Common\Cache\Cache``. All the cache drivers extend a base class ``Doctrine\Common\Cache\AbstractCache`` which implements -the before mentioned interface. +this interface. -The interface defines the following methods for you to publicly -use. +The interface defines the following public methods for you to implement: -- fetch($id) - Fetches an entry from the cache. -- contains($id) - Test if an entry exists in the cache. -- save($id, $data, $lifeTime = false) - Puts data into the cache. -- delete($id) - Deletes a cache entry. +- fetch($id) - Fetches an entry from the cache +- contains($id) - Test if an entry exists in the cache +- save($id, $data, $lifeTime = false) - Puts data into the cache +- delete($id) - Deletes a cache entry Each driver extends the ``AbstractCache`` class which defines a few abstract protected methods that each of the drivers must -implement. +implement: - \_doFetch($id) @@ -35,8 +34,8 @@ implement. - \_doSave($id, $data, $lifeTime = false) - \_doDelete($id) -The public methods ``fetch()``, ``contains()``, etc. utilize the -above protected methods that are implemented by the drivers. The +The public methods ``fetch()``, ``contains()`` etc. use the +above protected methods which are implemented by the drivers. The code is organized this way so that the protected methods in the drivers do the raw interaction with the cache implementation and the ``AbstractCache`` can build custom functionality on top of @@ -65,7 +64,7 @@ Memcache In order to use the Memcache cache driver you must have it compiled and enabled in your php.ini. You can read about Memcache -` on the PHP website `_. It will +`on the PHP website `_. It will give you a little background information about what it is and how you can use it as well as how to install it. @@ -90,7 +89,7 @@ Memcache. In order to use the Memcached cache driver you must have it compiled and enabled in your php.ini. You can read about Memcached -` on the PHP website `_. It will +`on the PHP website `_. It will give you a little background information about what it is and how you can use it as well as how to install it. @@ -129,10 +128,10 @@ Redis ~~~~~ In order to use the Redis cache driver you must have it compiled -and enabled in your php.ini. You can read about what is Redis +and enabled in your php.ini. You can read about what Redis is `from here `_. Also check `A PHP extension for Redis `_ for how you can use -and install Redis PHP extension. +and install the Redis PHP extension. Below is a simple example of how you could use the Redis cache driver by itself. @@ -151,8 +150,8 @@ Using Cache Drivers ------------------- In this section we'll describe how you can fully utilize the API of -the cache drivers to save cache, check if some cache exists, fetch -the cached data and delete the cached data. We'll use the +the cache drivers to save data to a cache, check if some cached data +exists, fetch the cached data and delete the cached data. We'll use the ``ArrayCache`` implementation as our example here. .. code-block:: php @@ -163,7 +162,7 @@ the cached data and delete the cached data. We'll use the Saving ~~~~~~ -To save some data to the cache driver it is as simple as using the +Saving some data to the cache driver is as simple as using the ``save()`` method. .. code-block:: php @@ -172,7 +171,7 @@ To save some data to the cache driver it is as simple as using the $cacheDriver->save('cache_id', 'my_data'); The ``save()`` method accepts three arguments which are described -below. +below: - ``$id`` - The cache id @@ -195,7 +194,7 @@ object, etc. Checking ~~~~~~~~ -Checking whether some cache exists is very simple, just use the +Checking whether cached data exists is very simple: just use the ``contains()`` method. It accepts a single argument which is the ID of the cache entry. @@ -213,7 +212,7 @@ Fetching Now if you want to retrieve some cache entry you can use the ``fetch()`` method. It also accepts a single argument just like -``contains()`` which is the ID of the cache entry. +``contains()`` which is again the ID of the cache entry. .. code-block:: php @@ -249,7 +248,7 @@ the ``deleteAll()`` method. Namespaces ~~~~~~~~~~ -If you heavily use caching in your application and utilize it in +If you heavily use caching in your application and use it in multiple parts of your application, or use it in different applications on the same server you may have issues with cache naming collisions. This can be worked around by using namespaces. @@ -265,8 +264,8 @@ Integrating with the ORM ------------------------ The Doctrine ORM package is tightly integrated with the cache -drivers to allow you to improve performance of various aspects of -Doctrine by just simply making some additional configurations and +drivers to allow you to improve the performance of various aspects of +Doctrine by simply making some additional configurations and method calls. Query Cache @@ -374,9 +373,9 @@ the cache driver. Clearing the Cache ------------------ -We've already shown you previously how you can use the API of the +We've already shown you how you can use the API of the cache drivers to manually delete cache entries. For your -convenience we offer a command line task for you to help you with +convenience we offer a command line task to help you with clearing the query, result and metadata cache. From the Doctrine command line you can run the following command. @@ -408,7 +407,7 @@ To clear the result cache use the ``--result`` option. $ ./doctrine clear-cache --result When you use the ``--result`` option you can use some other options -to be more specific about what queries result sets you want to +to be more specific about which queries' result sets you want to clear. Just like the API of the cache drivers you can clear based on an @@ -418,19 +417,19 @@ ID, regular expression, prefix or suffix. $ ./doctrine clear-cache --result --id=cache_id -Or if you want to clear based on a regular expressions. +Or if you want to clear based on a regular expressions: .. code-block:: php $ ./doctrine clear-cache --result --regex=users_.* -Or with a prefix. +Or with a prefix: .. code-block:: php $ ./doctrine clear-cache --result --prefix=users_ -And finally with a suffix. +And finally with a suffix: .. code-block:: php @@ -447,15 +446,15 @@ And finally with a suffix. Cache Slams ----------- -Something to be careful of when utilizing the cache drivers is -cache slams. If you have a heavily trafficked website with some +Something to be careful of when using the cache drivers is +"cache slams". Imagine you have a heavily trafficked website with some code that checks for the existence of a cache record and if it does not exist it generates the information and saves it to the cache. -Now if 100 requests were issued all at the same time and each one -sees the cache does not exist and they all try and insert the same +Now, if 100 requests were issued all at the same time and each one +sees the cache does not exist and they all try to insert the same cache entry it could lock up APC, Xcache, etc. and cause problems. Ways exist to work around this, like pre-populating your cache and -not letting your users requests populate the cache. +not letting your users' requests populate the cache. You can read more about cache slams `in this blog post `_. diff --git a/docs/en/reference/dql-doctrine-query-language.rst b/docs/en/reference/dql-doctrine-query-language.rst index e8348350e..0161eecf9 100644 --- a/docs/en/reference/dql-doctrine-query-language.rst +++ b/docs/en/reference/dql-doctrine-query-language.rst @@ -1626,8 +1626,7 @@ Aggregate Expressions .. code-block:: php - AggregateExpression ::= ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" | - "COUNT" "(" ["DISTINCT"] (IdentificationVariable | SingleValuedPathExpression) ")" + AggregateExpression ::= ("AVG" | "MAX" | "MIN" | "SUM" | "COUNT") "(" ["DISTINCT"] SimpleArithmeticExpression ")" Case Expressions ~~~~~~~~~~~~~~~~ diff --git a/docs/en/reference/improving-performance.rst b/docs/en/reference/improving-performance.rst index 9bc4c8632..d9de6c808 100644 --- a/docs/en/reference/improving-performance.rst +++ b/docs/en/reference/improving-performance.rst @@ -62,3 +62,7 @@ A lot of the points mentioned in the Best Practices chapter will also positively affect the performance of Doctrine. +Change Tracking policies +------------------------ + +See: :doc:`Change Tracking Policies ` diff --git a/docs/en/reference/second-level-cache.rst b/docs/en/reference/second-level-cache.rst index 03d5b6de4..d88e83fc6 100644 --- a/docs/en/reference/second-level-cache.rst +++ b/docs/en/reference/second-level-cache.rst @@ -466,7 +466,7 @@ Basic entity cache $country1 = $em->find('Country', 1); // Retrieve item from cache $country->setName("New Name"); - $em->persist($state); + $em->persist($country); $em->flush(); // Hit database to update the row and update cache $em->clear(); // Clear entity manager diff --git a/docs/en/reference/tools.rst b/docs/en/reference/tools.rst index a5f99d141..eb93831b9 100644 --- a/docs/en/reference/tools.rst +++ b/docs/en/reference/tools.rst @@ -507,3 +507,22 @@ defined ones) is possible through the command: new \MyProject\Tools\Console\Commands\AnotherCommand(), new \MyProject\Tools\Console\Commands\OneMoreCommand(), )); + + +Re-use console application +-------------------------- + +You are also able to retrieve and re-use the default console application. +Just call ``ConsoleRunner::createApplication(...)`` with an appropriate +HelperSet, like it is described in the configuration section. + +.. code-block:: php + + run(); + diff --git a/docs/en/reference/working-with-objects.rst b/docs/en/reference/working-with-objects.rst index a402be88c..a7e03bcc9 100644 --- a/docs/en/reference/working-with-objects.rst +++ b/docs/en/reference/working-with-objects.rst @@ -114,7 +114,7 @@ from newly opened EntityManager. $article = $em->find('Article', 1); This code only retrieves the ``Article`` instance with id 1 executing -a single SELECT statement against the user table in the database. +a single SELECT statement against the articles table in the database. You can still access the associated properties author and comments and the associated objects they contain. diff --git a/lib/Doctrine/ORM/Cache/CacheConfiguration.php b/lib/Doctrine/ORM/Cache/CacheConfiguration.php index 760352314..4891cac49 100644 --- a/lib/Doctrine/ORM/Cache/CacheConfiguration.php +++ b/lib/Doctrine/ORM/Cache/CacheConfiguration.php @@ -85,7 +85,7 @@ class CacheConfiguration } /** - * @return \Doctrine\ORM\Cache\QueryCacheValidator + * @return \Doctrine\ORM\Cache\RegionsConfiguration */ public function getRegionsConfiguration() { diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index 62f81939e..876f1ce57 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -64,6 +64,11 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory */ private $evm; + /** + * @var array + */ + private $embeddablesActiveNesting = array(); + /** * @param EntityManager $em */ @@ -142,15 +147,27 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory } if (!$class->isMappedSuperclass) { - foreach ($class->embeddedClasses as $property => $embeddableClass) { if (isset($embeddableClass['inherited'])) { continue; } + if (isset($this->embeddablesActiveNesting[$embeddableClass['class']])) { + throw MappingException::infiniteEmbeddableNesting($class->name, $property); + } + + $this->embeddablesActiveNesting[$class->name] = true; + $embeddableMetadata = $this->getMetadataFor($embeddableClass['class']); + + if ($embeddableMetadata->isEmbeddedClass) { + $this->addNestedEmbeddedClasses($embeddableMetadata, $class, $property); + } + $class->inlineEmbeddable($property, $embeddableMetadata); + + unset($this->embeddablesActiveNesting[$class->name]); } } @@ -370,6 +387,34 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory } } + /** + * Adds nested embedded classes metadata to a parent class. + * + * @param ClassMetadata $subClass Sub embedded class metadata to add nested embedded classes metadata from. + * @param ClassMetadata $parentClass Parent class to add nested embedded classes metadata to. + * @param string $prefix Embedded classes' prefix to use for nested embedded classes field names. + */ + private function addNestedEmbeddedClasses(ClassMetadata $subClass, ClassMetadata $parentClass, $prefix) + { + foreach ($subClass->embeddedClasses as $property => $embeddableClass) { + if (isset($embeddableClass['inherited'])) { + continue; + } + + $embeddableMetadata = $this->getMetadataFor($embeddableClass['class']); + + $parentClass->mapEmbedded(array( + 'fieldName' => $prefix . '.' . $property, + 'class' => $embeddableMetadata->name, + 'columnPrefix' => $embeddableClass['columnPrefix'], + 'declaredField' => $embeddableClass['declaredField'] + ? $prefix . '.' . $embeddableClass['declaredField'] + : $prefix, + 'originalField' => $embeddableClass['originalField'] ?: $property, + )); + } + } + /** * Adds inherited named queries to the subclass mapping. * diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index 96a71de18..76dd8f1e6 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -20,6 +20,7 @@ namespace Doctrine\ORM\Mapping; use BadMethodCallException; +use Doctrine\Instantiator\Instantiator; use InvalidArgumentException; use RuntimeException; use Doctrine\DBAL\Types\Type; @@ -643,11 +644,9 @@ class ClassMetadataInfo implements ClassMetadata public $reflFields = array(); /** - * The prototype from which new instances of the mapped class are created. - * - * @var object + * @var \Doctrine\Instantiator\InstantiatorInterface|null */ - private $_prototype; + private $instantiator; /** * Initializes a new ClassMetadata instance that will hold the object-relational mapping @@ -661,6 +660,7 @@ class ClassMetadataInfo implements ClassMetadata $this->name = $entityName; $this->rootEntityName = $entityName; $this->namingStrategy = $namingStrategy ?: new DefaultNamingStrategy(); + $this->instantiator = new Instantiator(); } /** @@ -907,16 +907,9 @@ class ClassMetadataInfo implements ClassMetadata */ public function newInstance() { - if ($this->_prototype === null) { - if (PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513) { - $this->_prototype = $this->reflClass->newInstanceWithoutConstructor(); - } else { - $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); - } - } - - return clone $this->_prototype; + return $this->instantiator->instantiate($this->name); } + /** * Restores some state that can not be serialized/unserialized. * @@ -927,17 +920,34 @@ class ClassMetadataInfo implements ClassMetadata public function wakeupReflection($reflService) { // Restore ReflectionClass and properties - $this->reflClass = $reflService->getClass($this->name); + $this->reflClass = $reflService->getClass($this->name); + $this->instantiator = $this->instantiator ?: new Instantiator(); + + $parentReflFields = array(); + + foreach ($this->embeddedClasses as $property => $embeddedClass) { + if (isset($embeddedClass['declaredField'])) { + $parentReflFields[$property] = new ReflectionEmbeddedProperty( + $parentReflFields[$embeddedClass['declaredField']], + $reflService->getAccessibleProperty( + $this->embeddedClasses[$embeddedClass['declaredField']]['class'], + $embeddedClass['originalField'] + ), + $embeddedClass['class'] + ); + + continue; + } + + $parentReflFields[$property] = $reflService->getAccessibleProperty($this->name, $property); + } foreach ($this->fieldMappings as $field => $mapping) { if (isset($mapping['declaredField'])) { - $declaringClass = isset($this->embeddedClasses[$mapping['declaredField']]['declared']) - ? $this->embeddedClasses[$mapping['declaredField']]['declared'] : $this->name; - $this->reflFields[$field] = new ReflectionEmbeddedProperty( - $reflService->getAccessibleProperty($declaringClass, $mapping['declaredField']), - $reflService->getAccessibleProperty($this->embeddedClasses[$mapping['declaredField']]['class'], $mapping['originalField']), - $this->embeddedClasses[$mapping['declaredField']]['class'] + $parentReflFields[$mapping['declaredField']], + $reflService->getAccessibleProperty($mapping['originalClass'], $mapping['originalField']), + $mapping['originalClass'] ); continue; } @@ -3171,15 +3181,13 @@ class ClassMetadataInfo implements ClassMetadata */ public function mapEmbedded(array $mapping) { - if ($this->isEmbeddedClass) { - throw MappingException::noEmbeddablesInEmbeddable($this->name); - } - $this->assertFieldNotMapped($mapping['fieldName']); $this->embeddedClasses[$mapping['fieldName']] = array( 'class' => $this->fullyQualifiedClassName($mapping['class']), 'columnPrefix' => $mapping['columnPrefix'], + 'declaredField' => isset($mapping['declaredField']) ? $mapping['declaredField'] : null, + 'originalField' => isset($mapping['originalField']) ? $mapping['originalField'] : null, ); } @@ -3192,8 +3200,15 @@ class ClassMetadataInfo implements ClassMetadata public function inlineEmbeddable($property, ClassMetadataInfo $embeddable) { foreach ($embeddable->fieldMappings as $fieldMapping) { - $fieldMapping['declaredField'] = $property; - $fieldMapping['originalField'] = $fieldMapping['fieldName']; + $fieldMapping['originalClass'] = isset($fieldMapping['originalClass']) + ? $fieldMapping['originalClass'] + : $embeddable->name; + $fieldMapping['declaredField'] = isset($fieldMapping['declaredField']) + ? $property . '.' . $fieldMapping['declaredField'] + : $property; + $fieldMapping['originalField'] = isset($fieldMapping['originalField']) + ? $fieldMapping['originalField'] + : $fieldMapping['fieldName']; $fieldMapping['fieldName'] = $property . "." . $fieldMapping['fieldName']; if (! empty($this->embeddedClasses[$property]['columnPrefix'])) { diff --git a/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php b/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php index ce35e7e9f..e51c15282 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php @@ -407,7 +407,7 @@ class DatabaseDriver implements MappingDriver case Type::STRING: case Type::TEXT: $fieldMapping['length'] = $column->getLength(); - $fieldMapping['fixed'] = $column->getFixed(); + $fieldMapping['options']['fixed'] = $column->getFixed(); break; case Type::DECIMAL: @@ -419,18 +419,18 @@ class DatabaseDriver implements MappingDriver case Type::INTEGER: case Type::BIGINT: case Type::SMALLINT: - $fieldMapping['unsigned'] = $column->getUnsigned(); + $fieldMapping['options']['unsigned'] = $column->getUnsigned(); break; } // Comment if (($comment = $column->getComment()) !== null) { - $fieldMapping['comment'] = $comment; + $fieldMapping['options']['comment'] = $comment; } // Default if (($default = $column->getDefault()) !== null) { - $fieldMapping['default'] = $default; + $fieldMapping['options']['default'] = $default; } return $fieldMapping; diff --git a/lib/Doctrine/ORM/Mapping/MappingException.php b/lib/Doctrine/ORM/Mapping/MappingException.php index 82d5a4585..7a8eaada6 100644 --- a/lib/Doctrine/ORM/Mapping/MappingException.php +++ b/lib/Doctrine/ORM/Mapping/MappingException.php @@ -782,11 +782,21 @@ class MappingException extends \Doctrine\ORM\ORMException ); } - public static function noEmbeddablesInEmbeddable($className) + /** + * @param string $className + * @param string $propertyName + * + * @return MappingException + */ + public static function infiniteEmbeddableNesting($className, $propertyName) { - return new self(sprintf( - "You embedded one or more embeddables in embeddable '%s', but this behavior is currently unsupported.", - $className - )); + return new self( + sprintf( + 'Infinite nesting detected for embedded property %s::%s. ' . + 'You cannot embed an embeddable from the same type inside an embeddable.', + $className, + $propertyName + ) + ); } } diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index c64e731c6..fea4f9a12 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -2939,8 +2939,7 @@ class Parser /** * AggregateExpression ::= - * ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" | - * "COUNT" "(" ["DISTINCT"] (IdentificationVariable | SingleValuedPathExpression) ")" + * ("AVG" | "MAX" | "MIN" | "SUM" | "COUNT") "(" ["DISTINCT"] SimpleArithmeticExpression ")" * * @return \Doctrine\ORM\Query\AST\AggregateExpression */ @@ -2962,9 +2961,7 @@ class Parser $isDistinct = true; } - $pathExp = ($lookaheadType === Lexer::T_COUNT) - ? $this->SingleValuedPathExpression() - : $this->SimpleArithmeticExpression(); + $pathExp = $this->SimpleArithmeticExpression(); $this->match(Lexer::T_CLOSE_PARENTHESIS); diff --git a/lib/Doctrine/ORM/Query/QueryException.php b/lib/Doctrine/ORM/Query/QueryException.php index f2fb61c71..16a10856a 100644 --- a/lib/Doctrine/ORM/Query/QueryException.php +++ b/lib/Doctrine/ORM/Query/QueryException.php @@ -248,7 +248,7 @@ class QueryException extends \Doctrine\ORM\ORMException public static function instanceOfUnrelatedClass($className, $rootClass) { return new self("Cannot check if a child of '" . $rootClass . "' is instanceof '" . $className . "', " . - "inheritance hierarchy exists between these two classes."); + "inheritance hierarchy does not exists between these two classes."); } /** diff --git a/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php b/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php index 2774dea68..b9afbfabf 100644 --- a/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php +++ b/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php @@ -32,7 +32,7 @@ class DefaultRepositoryFactory implements RepositoryFactory /** * The list of EntityRepository instances. * - * @var array<\Doctrine\Common\Persistence\ObjectRepository> + * @var \Doctrine\Common\Persistence\ObjectRepository[] */ private $repositoryList = array(); @@ -41,17 +41,13 @@ class DefaultRepositoryFactory implements RepositoryFactory */ public function getRepository(EntityManagerInterface $entityManager, $entityName) { - $entityName = ltrim($entityName, '\\'); + $className = $entityManager->getClassMetadata($entityName)->getName(); - if (isset($this->repositoryList[$entityName])) { - return $this->repositoryList[$entityName]; + if (isset($this->repositoryList[$className])) { + return $this->repositoryList[$className]; } - $repository = $this->createRepository($entityManager, $entityName); - - $this->repositoryList[$entityName] = $repository; - - return $repository; + return $this->repositoryList[$className] = $this->createRepository($entityManager, $entityName); } /** @@ -64,14 +60,11 @@ class DefaultRepositoryFactory implements RepositoryFactory */ protected function createRepository(EntityManagerInterface $entityManager, $entityName) { + /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */ $metadata = $entityManager->getClassMetadata($entityName); - $repositoryClassName = $metadata->customRepositoryClassName; - - if ($repositoryClassName === null) { - $configuration = $entityManager->getConfiguration(); - $repositoryClassName = $configuration->getDefaultRepositoryClassName(); - } + $repositoryClassName = $metadata->customRepositoryClassName + ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); return new $repositoryClassName($entityManager, $metadata); } -} \ No newline at end of file +} diff --git a/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php b/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php index 7e88615aa..c69e2342b 100644 --- a/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php +++ b/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php @@ -55,13 +55,29 @@ class ConsoleRunner * @return void */ static public function run(HelperSet $helperSet, $commands = array()) + { + $cli = self::createApplication($helperSet, $commands); + $cli->run(); + } + + /** + * Creates a console application with the given helperset and + * optional commands. + * + * @param \Symfony\Component\Console\Helper\HelperSet $helperSet + * @param array $commands + * + * @return \Symfony\Component\Console\Application + */ + static public function createApplication(HelperSet $helperSet, $commands = array()) { $cli = new Application('Doctrine Command Line Interface', Version::VERSION); $cli->setCatchExceptions(true); $cli->setHelperSet($helperSet); self::addCommands($cli); $cli->addCommands($commands); - $cli->run(); + + return $cli; } /** diff --git a/lib/Doctrine/ORM/Tools/EntityGenerator.php b/lib/Doctrine/ORM/Tools/EntityGenerator.php index bf208e277..918e4162b 100644 --- a/lib/Doctrine/ORM/Tools/EntityGenerator.php +++ b/lib/Doctrine/ORM/Tools/EntityGenerator.php @@ -714,9 +714,9 @@ public function __construct() */ protected function hasProperty($property, ClassMetadataInfo $metadata) { - if ($this->extendsClass()) { + if ($this->extendsClass() || class_exists($metadata->name)) { // don't generate property if its already on the base class. - $reflClass = new \ReflectionClass($this->getClassToExtend()); + $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name); if ($reflClass->hasProperty($property)) { return true; } @@ -743,9 +743,9 @@ public function __construct() */ protected function hasMethod($method, ClassMetadataInfo $metadata) { - if ($this->extendsClass()) { + if ($this->extendsClass() || class_exists($metadata->name)) { // don't generate method if its already on the base class. - $reflClass = new \ReflectionClass($this->getClassToExtend()); + $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name); if ($reflClass->hasMethod($method)) { return true; @@ -1173,7 +1173,7 @@ public function __construct() } $replacements = array( - '' => ucfirst($type) . ' ' . $variableName . ".\n", + '' => ucfirst($type) . ' ' . $variableName, '' => $methodTypeHint, '' => $variableType, '' => $variableName, diff --git a/lib/Doctrine/ORM/Tools/SchemaValidator.php b/lib/Doctrine/ORM/Tools/SchemaValidator.php index 0db5b7e0e..6652e4966 100644 --- a/lib/Doctrine/ORM/Tools/SchemaValidator.php +++ b/lib/Doctrine/ORM/Tools/SchemaValidator.php @@ -124,7 +124,7 @@ class SchemaValidator $ce[] = "The field " . $class->name . "#" . $fieldName . " is on the inverse side of a ". "bi-directional relationship, but the specified mappedBy association on the target-entity ". $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ". - "'inversedBy=".$fieldName."' attribute."; + "'inversedBy=\"" . $fieldName . "\"' attribute."; } elseif ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] != $fieldName) { $ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " are ". diff --git a/tests/Doctrine/Tests/Mocks/EntityManagerMock.php b/tests/Doctrine/Tests/Mocks/EntityManagerMock.php index b27e96c4b..74f4efcf0 100644 --- a/tests/Doctrine/Tests/Mocks/EntityManagerMock.php +++ b/tests/Doctrine/Tests/Mocks/EntityManagerMock.php @@ -86,13 +86,13 @@ class EntityManagerMock extends \Doctrine\ORM\EntityManager public static function create($conn, \Doctrine\ORM\Configuration $config = null, \Doctrine\Common\EventManager $eventManager = null) { - if (is_null($config)) { + if (null === $config) { $config = new \Doctrine\ORM\Configuration(); $config->setProxyDir(__DIR__ . '/../Proxies'); $config->setProxyNamespace('Doctrine\Tests\Proxies'); $config->setMetadataDriverImpl($config->newDefaultAnnotationDriver(array(), true)); } - if (is_null($eventManager)) { + if (null === $eventManager) { $eventManager = new \Doctrine\Common\EventManager(); } diff --git a/tests/Doctrine/Tests/Models/DDC1590/DDC1590Entity.php b/tests/Doctrine/Tests/Models/DDC1590/DDC1590Entity.php new file mode 100644 index 000000000..a4dff26fa --- /dev/null +++ b/tests/Doctrine/Tests/Models/DDC1590/DDC1590Entity.php @@ -0,0 +1,56 @@ +id; + } + + /** + * Set createdAt + * + * @param \DateTime $createdAt + * + * @return DDC1590User + */ + public function setCreatedAt($createdAt) + { + $this->created_at = $createdAt; + + return $this; + } + + /** + * Get createdAt + * + * @return \DateTime + */ + public function getCreatedAt() + { + return $this->created_at; + } +} diff --git a/tests/Doctrine/Tests/Models/DDC1590/DDC1590User.php b/tests/Doctrine/Tests/Models/DDC1590/DDC1590User.php new file mode 100644 index 000000000..436ab0d54 --- /dev/null +++ b/tests/Doctrine/Tests/Models/DDC1590/DDC1590User.php @@ -0,0 +1,18 @@ +_em->getConnection()->getDatabasePlatform() instanceof PostgreSqlPlatform AND ! $this->_em->getConnection()->getDatabasePlatform() instanceof SQLServerPlatform) { $this->assertArrayHasKey('columnUnsigned', $metadata->fieldMappings); - $this->assertTrue($metadata->fieldMappings['columnUnsigned']['unsigned']); + $this->assertTrue($metadata->fieldMappings['columnUnsigned']['options']['unsigned']); } $this->assertArrayHasKey('columnComment', $metadata->fieldMappings); - $this->assertEquals('test_comment', $metadata->fieldMappings['columnComment']['comment']); + $this->assertEquals('test_comment', $metadata->fieldMappings['columnComment']['options']['comment']); $this->assertArrayHasKey('columnDefault', $metadata->fieldMappings); - $this->assertEquals('test_default', $metadata->fieldMappings['columnDefault']['default']); + $this->assertEquals('test_default', $metadata->fieldMappings['columnDefault']['options']['default']); $this->assertArrayHasKey('columnDecimal', $metadata->fieldMappings); $this->assertEquals(4, $metadata->fieldMappings['columnDecimal']['precision']); diff --git a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php index 12b941efc..705802306 100644 --- a/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/EntityRepositoryTest.php @@ -611,6 +611,33 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->getConfiguration()->setDefaultRepositoryClassName("Doctrine\Tests\Models\DDC753\DDC753InvalidRepository"); } + /** + * @group DDC-3257 + */ + public function testSingleRepositoryInstanceForDifferentEntityAliases() + { + $config = $this->_em->getConfiguration(); + + $config->addEntityNamespace('Aliased', 'Doctrine\Tests\Models\CMS'); + $config->addEntityNamespace('AliasedAgain', 'Doctrine\Tests\Models\CMS'); + + $repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser'); + + $this->assertSame($repository, $this->_em->getRepository('Aliased:CmsUser')); + $this->assertSame($repository, $this->_em->getRepository('AliasedAgain:CmsUser')); + } + + /** + * @group DDC-3257 + */ + public function testCanRetrieveRepositoryFromClassNameWithLeadingBackslash() + { + $this->assertSame( + $this->_em->getRepository('\\Doctrine\\Tests\\Models\\CMS\\CmsUser'), + $this->_em->getRepository('Doctrine\\Tests\\Models\\CMS\\CmsUser') + ); + } + /** * @group DDC-1376 * diff --git a/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php b/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php index 4e34004b8..28a7e2664 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php @@ -32,6 +32,7 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $person->address->street = "United States of Tara Street"; $person->address->zip = "12345"; $person->address->city = "funkytown"; + $person->address->country = new DDC93Country('Germany'); // 1. check saving value objects works $this->_em->persist($person); @@ -46,11 +47,14 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals('United States of Tara Street', $person->address->street); $this->assertEquals('12345', $person->address->zip); $this->assertEquals('funkytown', $person->address->city); + $this->assertInstanceOf(DDC93Country::CLASSNAME, $person->address->country); + $this->assertEquals('Germany', $person->address->country->name); // 3. check changing value objects works $person->address->street = "Street"; $person->address->zip = "54321"; $person->address->city = "another town"; + $person->address->country->name = "United States of America"; $this->_em->flush(); $this->_em->clear(); @@ -60,6 +64,7 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals('Street', $person->address->street); $this->assertEquals('54321', $person->address->zip); $this->assertEquals('another town', $person->address->city); + $this->assertEquals('United States of America', $person->address->country->name); // 4. check deleting works $personId = $person->id;; @@ -78,6 +83,7 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $person->address->street = "Tree"; $person->address->zip = "12345"; $person->address->city = "funkytown"; + $person->address->country = new DDC93Country('United States of America'); $this->_em->persist($person); } @@ -94,6 +100,8 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals('Tree', $person->address->street); $this->assertEquals('12345', $person->address->zip); $this->assertEquals('funkytown', $person->address->city); + $this->assertInstanceOf(DDC93Country::CLASSNAME, $person->address->country); + $this->assertEquals('United States of America', $person->address->country->name); } $dql = "SELECT p FROM " . __NAMESPACE__ . "\DDC93Person p"; @@ -103,6 +111,7 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals('Tree', $person['address.street']); $this->assertEquals('12345', $person['address.zip']); $this->assertEquals('funkytown', $person['address.city']); + $this->assertEquals('United States of America', $person['address.country.name']); } } @@ -115,32 +124,41 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->markTestSkipped('SLC does not work with UPDATE/DELETE queries through EM.'); } - $person = new DDC93Person('Johannes', new DDC93Address('Moo', '12345', 'Karlsruhe')); + $person = new DDC93Person('Johannes', new DDC93Address('Moo', '12345', 'Karlsruhe', new DDC93Country('Germany'))); $this->_em->persist($person); $this->_em->flush($person); // SELECT - $selectDql = "SELECT p FROM " . __NAMESPACE__ ."\\DDC93Person p WHERE p.address.city = :city"; + $selectDql = "SELECT p FROM " . __NAMESPACE__ ."\\DDC93Person p WHERE p.address.city = :city AND p.address.country.name = :country"; $loadedPerson = $this->_em->createQuery($selectDql) ->setParameter('city', 'Karlsruhe') + ->setParameter('country', 'Germany') ->getSingleResult(); $this->assertEquals($person, $loadedPerson); - $this->assertNull($this->_em->createQuery($selectDql)->setParameter('city', 'asdf')->getOneOrNullResult()); + $this->assertNull( + $this->_em->createQuery($selectDql) + ->setParameter('city', 'asdf') + ->setParameter('country', 'Germany') + ->getOneOrNullResult() + ); // UPDATE - $updateDql = "UPDATE " . __NAMESPACE__ . "\\DDC93Person p SET p.address.street = :street WHERE p.address.city = :city"; + $updateDql = "UPDATE " . __NAMESPACE__ . "\\DDC93Person p SET p.address.street = :street, p.address.country.name = :country WHERE p.address.city = :city"; $this->_em->createQuery($updateDql) ->setParameter('street', 'Boo') + ->setParameter('country', 'DE') ->setParameter('city', 'Karlsruhe') ->execute(); $this->_em->refresh($person); $this->assertEquals('Boo', $person->address->street); + $this->assertEquals('DE', $person->address->country->name); // DELETE - $this->_em->createQuery("DELETE " . __NAMESPACE__ . "\\DDC93Person p WHERE p.address.city = :city") + $this->_em->createQuery("DELETE " . __NAMESPACE__ . "\\DDC93Person p WHERE p.address.city = :city AND p.address.country.name = :country") ->setParameter('city', 'Karlsruhe') + ->setParameter('country', 'DE') ->execute(); $this->_em->clear(); @@ -165,43 +183,24 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals($car, $reloadedCar); } - public function testEmbeddableWithinEmbeddable() - { - $this->setExpectedException( - 'Doctrine\ORM\Mapping\MappingException', - sprintf( - "You embedded one or more embeddables in embeddable '%s', but this behavior is currently unsupported.", - __NAMESPACE__ . '\DDC93ContactInfo' - ) - ); - - $this->_schemaTool->createSchema(array( - $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC93Customer'), - $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC93ContactInfo'), - $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC93PhoneNumber') - )); - } - public function testInlineEmbeddableWithPrefix() { - $expectedColumnName = 'foobar_id'; + $metadata = $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC3028PersonWithPrefix'); - $actualColumnName = $this->_em - ->getClassMetadata(__NAMESPACE__ . '\DDC3028PersonWithPrefix') - ->getColumnName('id.id'); - - $this->assertEquals($expectedColumnName, $actualColumnName); + $this->assertEquals('foobar_id', $metadata->getColumnName('id.id')); + $this->assertEquals('bloo_foo_id', $metadata->getColumnName('nested.nestedWithPrefix.id')); + $this->assertEquals('bloo_nestedWithEmptyPrefix_id', $metadata->getColumnName('nested.nestedWithEmptyPrefix.id')); + $this->assertEquals('bloo_id', $metadata->getColumnName('nested.nestedWithPrefixFalse.id')); } public function testInlineEmbeddableEmptyPrefix() { - $expectedColumnName = 'id_id'; + $metadata = $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC3028PersonEmptyPrefix'); - $actualColumnName = $this->_em - ->getClassMetadata(__NAMESPACE__ . '\DDC3028PersonEmptyPrefix') - ->getColumnName('id.id'); - - $this->assertEquals($expectedColumnName, $actualColumnName); + $this->assertEquals('id_id', $metadata->getColumnName('id.id')); + $this->assertEquals('nested_foo_id', $metadata->getColumnName('nested.nestedWithPrefix.id')); + $this->assertEquals('nested_nestedWithEmptyPrefix_id', $metadata->getColumnName('nested.nestedWithEmptyPrefix.id')); + $this->assertEquals('nested_id', $metadata->getColumnName('nested.nestedWithPrefixFalse.id')); } public function testInlineEmbeddablePrefixFalse() @@ -223,6 +222,33 @@ class ValueObjectsTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertTrue($isFieldMapped); } + + /** + * @dataProvider getInfiniteEmbeddableNestingData + */ + public function testThrowsExceptionOnInfiniteEmbeddableNesting($embeddableClassName, $declaredEmbeddableClassName) + { + $this->setExpectedException( + 'Doctrine\ORM\Mapping\MappingException', + sprintf( + 'Infinite nesting detected for embedded property %s::nested. ' . + 'You cannot embed an embeddable from the same type inside an embeddable.', + __NAMESPACE__ . '\\' . $declaredEmbeddableClassName + ) + ); + + $this->_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\\' . $embeddableClassName), + )); + } + + public function getInfiniteEmbeddableNestingData() + { + return array( + array('DDCInfiniteNestingEmbeddable', 'DDCInfiniteNestingEmbeddable'), + array('DDCNestingEmbeddable1', 'DDCNestingEmbeddable4'), + ); + } } @@ -297,6 +323,24 @@ class DDC93Car extends DDC93Vehicle { } +/** + * @Embeddable + */ +class DDC93Country +{ + const CLASSNAME = __CLASS__; + + /** + * @Column(type="string", nullable=true) + */ + public $name; + + public function __construct($name = null) + { + $this->name = $name; + } +} + /** * @Embeddable */ @@ -316,12 +360,15 @@ class DDC93Address * @Column(type="string") */ public $city; + /** @Embedded(class = "DDC93Country") */ + public $country; - public function __construct($street = null, $zip = null, $city = null) + public function __construct($street = null, $zip = null, $city = null, DDC93Country $country = null) { $this->street = $street; $this->zip = $zip; $this->city = $city; + $this->country = $country; } } @@ -338,8 +385,14 @@ class DDC93Customer /** @Embeddable */ class DDC93ContactInfo { + const CLASSNAME = __CLASS__; + + /** + * @Column(type="string") + */ + public $email; /** @Embedded(class = "DDC93Address") */ - private $address; + public $address; } /** @@ -352,9 +405,13 @@ class DDC3028PersonWithPrefix /** @Embedded(class="DDC3028Id", columnPrefix = "foobar_") */ public $id; - public function __construct(DDC3028Id $id = null) + /** @Embedded(class="DDC3028NestedEmbeddable", columnPrefix = "bloo_") */ + public $nested; + + public function __construct(DDC3028Id $id = null, DDC3028NestedEmbeddable $nested = null) { $this->id = $id; + $this->nested = $nested; } } @@ -368,9 +425,13 @@ class DDC3028PersonEmptyPrefix /** @Embedded(class="DDC3028Id", columnPrefix = "") */ public $id; - public function __construct(DDC3028Id $id = null) + /** @Embedded(class="DDC3028NestedEmbeddable", columnPrefix = "") */ + public $nested; + + public function __construct(DDC3028Id $id = null, DDC3028NestedEmbeddable $nested = null) { $this->id = $id; + $this->nested = $nested; } } @@ -408,6 +469,33 @@ class DDC3028Id } } +/** + * @Embeddable + */ +class DDC3028NestedEmbeddable +{ + const CLASSNAME = __CLASS__; + + /** @Embedded(class="DDC3028Id", columnPrefix = "foo_") */ + public $nestedWithPrefix; + + /** @Embedded(class="DDC3028Id", columnPrefix = "") */ + public $nestedWithEmptyPrefix; + + /** @Embedded(class="DDC3028Id", columnPrefix = false) */ + public $nestedWithPrefixFalse; + + public function __construct( + DDC3028Id $nestedWithPrefix = null, + DDC3028Id $nestedWithEmptyPrefix = null, + DDC3028Id $nestedWithPrefixFalse = null + ) { + $this->nestedWithPrefix = $nestedWithPrefix; + $this->nestedWithEmptyPrefix = $nestedWithEmptyPrefix; + $this->nestedWithPrefixFalse = $nestedWithPrefixFalse; + } +} + /** * @MappedSuperclass */ @@ -426,3 +514,72 @@ abstract class DDC3027Animal class DDC3027Dog extends DDC3027Animal { } + +/** + * @Embeddable + */ +class DDCInfiniteNestingEmbeddable +{ + /** @Embedded(class="DDCInfiniteNestingEmbeddable") */ + public $nested; +} + +/** + * @Embeddable + */ +class DDCNestingEmbeddable1 +{ + /** @Embedded(class="DDC3028Id") */ + public $id1; + + /** @Embedded(class="DDC3028Id") */ + public $id2; + + /** @Embedded(class="DDCNestingEmbeddable2") */ + public $nested; +} + +/** + * @Embeddable + */ +class DDCNestingEmbeddable2 +{ + /** @Embedded(class="DDC3028Id") */ + public $id1; + + /** @Embedded(class="DDC3028Id") */ + public $id2; + + /** @Embedded(class="DDCNestingEmbeddable3") */ + public $nested; +} + +/** + * @Embeddable + */ +class DDCNestingEmbeddable3 +{ + /** @Embedded(class="DDC3028Id") */ + public $id1; + + /** @Embedded(class="DDC3028Id") */ + public $id2; + + /** @Embedded(class="DDCNestingEmbeddable4") */ + public $nested; +} + +/** + * @Embeddable + */ +class DDCNestingEmbeddable4 +{ + /** @Embedded(class="DDC3028Id") */ + public $id1; + + /** @Embedded(class="DDC3028Id") */ + public $id2; + + /** @Embedded(class="DDCNestingEmbeddable1") */ + public $nested; +} diff --git a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php index 2c35dc192..0ffb41c18 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php @@ -2,8 +2,10 @@ namespace Doctrine\Tests\ORM\Mapping; +use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Events; +use Doctrine\ORM\Mapping\DefaultNamingStrategy; require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php'; @@ -12,7 +14,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testClassMetadataInstanceSerialization() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); // Test initial state $this->assertTrue(count($cm->getReflectionProperties()) == 0); @@ -36,7 +38,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $serialized = serialize($cm); $cm = unserialize($serialized); - $cm->wakeupReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->wakeupReflection(new RuntimeReflectionService()); // Check state $this->assertTrue(count($cm->getReflectionProperties()) > 0); @@ -61,7 +63,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testFieldIsNullable() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); // Explicit Nullable $cm->mapField(array('fieldName' => 'status', 'nullable' => true, 'type' => 'string', 'length' => 50)); @@ -84,7 +86,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php"; $cm = new ClassMetadata('DoctrineGlobal_Article'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapManyToMany(array( 'fieldName' => 'author', 'targetEntity' => 'DoctrineGlobal_User', @@ -101,7 +103,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testMapManyToManyJoinTableDefaults() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapManyToMany( array( 'fieldName' => 'groups', @@ -121,7 +123,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testSerializeManyToManyJoinTableCascade() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapManyToMany( array( 'fieldName' => 'groups', @@ -143,7 +145,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php"; $cm = new ClassMetadata('DoctrineGlobal_User'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->setDiscriminatorMap(array('descr' => 'DoctrineGlobal_Article', 'foo' => 'DoctrineGlobal_User')); $this->assertEquals("DoctrineGlobal_Article", $cm->discriminatorMap['descr']); @@ -158,7 +160,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php"; $cm = new ClassMetadata('DoctrineGlobal_User'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->setSubclasses(array('DoctrineGlobal_Article')); $this->assertEquals("DoctrineGlobal_Article", $cm->subClasses[0]); @@ -174,7 +176,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $field['type'] = 'string'; $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->setExpectedException('Doctrine\ORM\Mapping\MappingException'); $cm->setVersionMapping($field); @@ -183,7 +185,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testGetSingleIdentifierFieldName_MultipleIdentifierEntity_ThrowsException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->isIdentifierComposite = true; $this->setExpectedException('Doctrine\ORM\Mapping\MappingException'); @@ -193,7 +195,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testDuplicateAssociationMappingException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $a1 = array('fieldName' => 'foo', 'sourceEntity' => 'stdClass', 'targetEntity' => 'stdClass', 'mappedBy' => 'foo'); $a2 = array('fieldName' => 'foo', 'sourceEntity' => 'stdClass', 'targetEntity' => 'stdClass', 'mappedBy' => 'foo'); @@ -206,7 +208,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testDuplicateColumnName_ThrowsMappingException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapField(array('fieldName' => 'name', 'columnName' => 'name')); @@ -217,7 +219,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testDuplicateColumnName_DiscriminatorColumn_ThrowsMappingException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapField(array('fieldName' => 'name', 'columnName' => 'name')); @@ -228,7 +230,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testDuplicateColumnName_DiscriminatorColumn2_ThrowsMappingException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->setDiscriminatorColumn(array('name' => 'name')); @@ -239,7 +241,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testDuplicateFieldAndAssociationMapping1_ThrowsException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapField(array('fieldName' => 'name', 'columnName' => 'name')); @@ -250,7 +252,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testDuplicateFieldAndAssociationMapping2_ThrowsException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapOneToOne(array('fieldName' => 'name', 'targetEntity' => 'CmsUser')); @@ -264,7 +266,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testGetTemporaryTableNameSchema() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->setTableName('foo.bar'); @@ -274,7 +276,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testDefaultTableName() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); // When table's name is not given $primaryTable = array(); @@ -284,7 +286,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $this->assertEquals('CmsUser', $cm->table['name']); $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); // When joinTable's name is not given $cm->mapManyToMany(array( 'fieldName' => 'user', @@ -298,7 +300,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testDefaultJoinColumnName() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); // this is really dirty, but it's the simplest way to test whether // joinColumn's name will be automatically set to user_id @@ -309,7 +311,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $this->assertEquals('user_id', $cm->associationMappings['user']['joinColumns'][0]['name']); $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapManyToMany(array( 'fieldName' => 'user', 'targetEntity' => 'CmsUser', @@ -372,7 +374,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testSetMultipleIdentifierSetsComposite() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapField(array('fieldName' => 'name')); $cm->mapField(array('fieldName' => 'username')); @@ -387,7 +389,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testMappingNotFound() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->setExpectedException('Doctrine\ORM\Mapping\MappingException', "No mapping found for field 'foo' on class 'Doctrine\Tests\Models\CMS\CmsUser'."); $cm->getFieldMapping('foo'); @@ -399,7 +401,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testJoinTableMappingDefaults() { $cm = new ClassMetadata('DoctrineGlobal_Article'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapManyToMany(array('fieldName' => 'author', 'targetEntity' => 'Doctrine\Tests\Models\CMS\CmsUser')); @@ -412,7 +414,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testMapIdentifierAssociation() { $cm = new ClassMetadata('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapOneToOne(array( 'fieldName' => 'article', @@ -431,7 +433,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testOrphanRemovalIdentifierAssociation() { $cm = new ClassMetadata('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'The orphan removal option is not allowed on an association that'); $cm->mapOneToOne(array( @@ -449,7 +451,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testInverseIdentifierAssociation() { $cm = new ClassMetadata('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'An inverse association is not allowed to be identifier in'); @@ -468,7 +470,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testIdentifierAssociationManyToMany() { $cm = new ClassMetadata('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->setExpectedException('Doctrine\ORM\Mapping\MappingException', 'Many-to-many or one-to-many associations are not allowed to be identifier in'); @@ -488,7 +490,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $this->setExpectedException('Doctrine\ORM\Mapping\MappingException', "The field or association mapping misses the 'fieldName' attribute in entity 'Doctrine\Tests\Models\CMS\CmsUser'."); $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapField(array('fieldName' => '')); } @@ -496,7 +498,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testRetrievalOfNamedQueries() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->assertEquals(0, count($cm->getNamedQueries())); @@ -515,7 +517,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testRetrievalOfResultSetMappings() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->assertEquals(0, count($cm->getSqlResultSetMappings())); @@ -535,7 +537,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testExistanceOfNamedQuery() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addNamedQuery(array( @@ -553,7 +555,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testRetrieveOfNamedNativeQuery() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addNamedNativeQuery(array( 'name' => 'find-all', @@ -586,7 +588,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testRetrieveOfSqlResultSetMapping() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addSqlResultSetMapping(array( 'name' => 'find-all', @@ -644,7 +646,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testExistanceOfSqlResultSetMapping() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addSqlResultSetMapping(array( 'name' => 'find-all', @@ -665,7 +667,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testExistanceOfNamedNativeQuery() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addNamedNativeQuery(array( @@ -682,7 +684,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testRetrieveOfNamedQuery() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addNamedQuery(array( @@ -699,7 +701,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testRetrievalOfNamedNativeQueries() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->assertEquals(0, count($cm->getNamedNativeQueries())); @@ -720,7 +722,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase { $metadata = new ClassMetadata('Doctrine\Tests\Models\Company\CompanyContract'); - $metadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $metadata->initializeReflection(new RuntimeReflectionService()); $metadata->addEntityListener(\Doctrine\ORM\Events::prePersist, 'CompanyContractListener', 'prePersistHandler'); $metadata->addEntityListener(\Doctrine\ORM\Events::postPersist, 'CompanyContractListener', 'postPersistHandler'); @@ -737,7 +739,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testNamingCollisionNamedQueryShouldThrowException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addNamedQuery(array( 'name' => 'userById', @@ -759,7 +761,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testNamingCollisionNamedNativeQueryShouldThrowException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addNamedNativeQuery(array( 'name' => 'find-all', @@ -785,7 +787,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testNamingCollisionSqlResultSetMappingShouldThrowException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addSqlResultSetMapping(array( 'name' => 'find-all', @@ -813,7 +815,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase { $user = new \Doctrine\Tests\Models\CMS\CmsUser(); $cm = new ClassMetadata('DOCTRINE\TESTS\MODELS\CMS\CMSUSER'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $cm->name); } @@ -824,11 +826,11 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testLifecycleCallbackNotFound() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addLifecycleCallback('notfound', 'postLoad'); $this->setExpectedException("Doctrine\ORM\Mapping\MappingException", "Entity 'Doctrine\Tests\Models\CMS\CmsUser' has no method 'notfound' to be registered as lifecycle callback."); - $cm->validateLifecycleCallbacks(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->validateLifecycleCallbacks(new RuntimeReflectionService()); } /** @@ -837,7 +839,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testTargetEntityNotFound() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapManyToOne(array('fieldName' => 'address', 'targetEntity' => 'UnknownClass')); $this->setExpectedException("Doctrine\ORM\Mapping\MappingException", "The target-entity Doctrine\Tests\Models\CMS\UnknownClass cannot be found in 'Doctrine\Tests\Models\CMS\CmsUser#address'."); @@ -853,7 +855,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testNameIsMandatoryForNamedQueryMappingException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addNamedQuery(array( 'query' => 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u', )); @@ -868,7 +870,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testNameIsMandatoryForNameNativeQueryMappingException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addNamedQuery(array( 'query' => 'SELECT * FROM cms_users', 'resultClass' => 'Doctrine\Tests\Models\CMS\CmsUser', @@ -885,7 +887,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testNameIsMandatoryForEntityNameSqlResultSetMappingException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addSqlResultSetMapping(array( 'name' => 'find-all', 'entities' => array( @@ -903,7 +905,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testNameIsMandatoryForDiscriminatorColumnsMappingException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->setDiscriminatorColumn(array()); } @@ -919,9 +921,9 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $articleMetadata = new ClassMetadata('DoctrineGlobal_Article', $namingStrategy); $routingMetadata = new ClassMetadata('Doctrine\Tests\Models\Routing\RoutingLeg',$namingStrategy); - $addressMetadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); - $articleMetadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); - $routingMetadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $addressMetadata->initializeReflection(new RuntimeReflectionService()); + $articleMetadata->initializeReflection(new RuntimeReflectionService()); + $routingMetadata->initializeReflection(new RuntimeReflectionService()); $addressMetadata->mapManyToMany(array( 'fieldName' => 'user', @@ -947,7 +949,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $namingStrategy = new MyPrefixNamingStrategy(); $metadata = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress', $namingStrategy); - $metadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $metadata->initializeReflection(new RuntimeReflectionService()); $metadata->mapField(array('fieldName'=>'country')); $metadata->mapField(array('fieldName'=>'city')); @@ -964,7 +966,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testInvalidCascade() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->setExpectedException("Doctrine\ORM\Mapping\MappingException", "You have specified invalid cascade options for Doctrine\Tests\Models\CMS\CmsUser::\$address: 'invalid'; available options: 'remove', 'persist', 'refresh', 'merge', and 'detach'"); @@ -980,7 +982,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testInvalidPropertyAssociationOverrideNameException() { $cm = new ClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Admin'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapManyToOne(array('fieldName' => 'address', 'targetEntity' => 'DDC964Address')); $cm->setAssociationOverride('invalidPropertyName', array()); @@ -994,7 +996,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testInvalidPropertyAttributeOverrideNameException() { $cm = new ClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Guest'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapField(array('fieldName' => 'name')); $cm->setAttributeOverride('invalidPropertyName', array()); @@ -1008,7 +1010,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testInvalidOverrideAttributeFieldTypeException() { $cm = new ClassMetadata('Doctrine\Tests\Models\DDC964\DDC964Guest'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapField(array('fieldName' => 'name', 'type'=>'string')); $cm->setAttributeOverride('name', array('type'=>'date')); @@ -1023,7 +1025,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testInvalidEntityListenerClassException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addEntityListener(Events::postLoad, '\InvalidClassName', 'postLoadHandler'); } @@ -1037,7 +1039,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testInvalidEntityListenerMethodException() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->addEntityListener(Events::postLoad, '\Doctrine\Tests\Models\Company\CompanyContractListener', 'invalidMethod'); } @@ -1045,7 +1047,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testManyToManySelfReferencingNamingStrategyDefaults() { $cm = new ClassMetadata('Doctrine\Tests\Models\CustomType\CustomTypeParent'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->mapManyToMany( array( 'fieldName' => 'friendsWithMe', @@ -1072,7 +1074,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testSetSequenceGeneratorThrowsExceptionWhenSequenceNameIsMissing() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $this->setExpectedException('Doctrine\ORM\Mapping\MappingException'); $cm->setSequenceGeneratorDefinition(array()); @@ -1084,7 +1086,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase public function testQuotedSequenceName() { $cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); - $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService); + $cm->initializeReflection(new RuntimeReflectionService()); $cm->setSequenceGeneratorDefinition(array('sequenceName' => '`foo`')); @@ -1100,6 +1102,29 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase $this->assertFalse($class->isIdentifier('foo')); } + + /** + * @group DDC-3120 + */ + public function testCanInstantiateInternalPhpClassSubclass() + { + $classMetadata = new ClassMetadata(__NAMESPACE__ . '\\MyArrayObjectEntity'); + + $this->assertInstanceOf(__NAMESPACE__ . '\\MyArrayObjectEntity', $classMetadata->newInstance()); + } + + /** + * @group DDC-3120 + */ + public function testCanInstantiateInternalPhpClassSubclassFromUnserializedMetadata() + { + /* @var $classMetadata ClassMetadata */ + $classMetadata = unserialize(serialize(new ClassMetadata(__NAMESPACE__ . '\\MyArrayObjectEntity'))); + + $classMetadata->wakeupReflection(new RuntimeReflectionService()); + + $this->assertInstanceOf(__NAMESPACE__ . '\\MyArrayObjectEntity', $classMetadata->newInstance()); + } } /** @@ -1111,7 +1136,7 @@ class DDC2700MappedSuperClass private $foo; } -class MyNamespacedNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy +class MyNamespacedNamingStrategy extends DefaultNamingStrategy { /** * {@inheritdoc} @@ -1126,7 +1151,7 @@ class MyNamespacedNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStra } } -class MyPrefixNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy +class MyPrefixNamingStrategy extends DefaultNamingStrategy { /** * {@inheritdoc} @@ -1136,3 +1161,7 @@ class MyPrefixNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy return strtolower($this->classToTableName($className)) . '_' . $propertyName; } } + +class MyArrayObjectEntity extends \ArrayObject +{ +} diff --git a/tests/Doctrine/Tests/ORM/Mapping/XmlMappingDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/XmlMappingDriverTest.php index f810e367d..3827c4173 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/XmlMappingDriverTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/XmlMappingDriverTest.php @@ -65,7 +65,9 @@ class XmlMappingDriverTest extends AbstractMappingDriverTest array( 'name' => array( 'class' => 'Doctrine\Tests\Models\ValueObjects\Name', - 'columnPrefix' => 'nm_' + 'columnPrefix' => 'nm_', + 'declaredField' => null, + 'originalField' => null, ) ), $class->embeddedClasses diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index e886307f6..0b5a60c96 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -263,6 +263,24 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ); } + /** + * @group DDC-3276 + */ + public function testSupportsAggregateCountFunctionWithSimpleArithmetic() + { + $connMock = $this->_em->getConnection(); + $orgPlatform = $connMock->getDatabasePlatform(); + + $connMock->setDatabasePlatform(new \Doctrine\DBAL\Platforms\MySqlPlatform); + + $this->assertSqlGeneration( + 'SELECT COUNT(CONCAT(u.id, u.name)) FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY u.id', + 'SELECT COUNT(CONCAT(c0_.id, c0_.name)) AS sclr_0 FROM cms_users c0_ GROUP BY c0_.id' + ); + + $connMock->setDatabasePlatform($orgPlatform); + } + public function testSupportsWhereClauseWithPositionalParameter() { $this->assertSqlGeneration( diff --git a/tests/Doctrine/Tests/ORM/Tools/Console/ConsoleRunnerTest.php b/tests/Doctrine/Tests/ORM/Tools/Console/ConsoleRunnerTest.php new file mode 100644 index 000000000..9d1966534 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Tools/Console/ConsoleRunnerTest.php @@ -0,0 +1,26 @@ +assertInstanceOf('Symfony\Component\Console\Application', $app); + $this->assertSame($helperSet, $app->getHelperSet()); + $this->assertEquals(Version::VERSION, $app->getVersion()); + } +} diff --git a/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php b/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php index 6394f6399..1a41dee83 100644 --- a/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php @@ -547,6 +547,79 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase $this->assertSame($reflClass->hasMethod('getAddress'), false); } + /** + * @group DDC-1590 + */ + public function testMethodsAndPropertiesAreNotDuplicatedInChildClasses() + { + $cmf = new ClassMetadataFactory(); + $em = $this->_getTestEntityManager(); + + $cmf->setEntityManager($em); + + $ns = $this->_namespace; + $nsdir = $this->_tmpDir . '/' . $ns; + + $content = str_replace( + 'namespace Doctrine\Tests\Models\DDC1590', + 'namespace ' . $ns, + file_get_contents(__DIR__ . '/../../Models/DDC1590/DDC1590User.php') + ); + + $fname = $nsdir . "/DDC1590User.php"; + file_put_contents($fname, $content); + require $fname; + + + $metadata = $cmf->getMetadataFor($ns . '\DDC1590User'); + $this->_generator->writeEntityClass($metadata, $this->_tmpDir); + + // class DDC1590User extends DDC1590Entity { ... } + $source = file_get_contents($fname); + + // class _DDC1590User extends DDC1590Entity { ... } + $source2 = str_replace('class DDC1590User', 'class _DDC1590User', $source); + $fname2 = $nsdir . "/_DDC1590User.php"; + file_put_contents($fname2, $source2); + require $fname2; + + // class __DDC1590User { ... } + $source3 = str_replace('class DDC1590User extends DDC1590Entity', 'class __DDC1590User', $source); + $fname3 = $nsdir . "/__DDC1590User.php"; + file_put_contents($fname3, $source3); + require $fname3; + + + // class _DDC1590User extends DDC1590Entity { ... } + $rc2 = new \ReflectionClass($ns.'\_DDC1590User'); + + $this->assertTrue($rc2->hasProperty('name')); + $this->assertTrue($rc2->hasProperty('id')); + $this->assertTrue($rc2->hasProperty('created_at')); + + $this->assertTrue($rc2->hasMethod('getName')); + $this->assertTrue($rc2->hasMethod('setName')); + $this->assertTrue($rc2->hasMethod('getId')); + $this->assertFalse($rc2->hasMethod('setId')); + $this->assertTrue($rc2->hasMethod('getCreatedAt')); + $this->assertTrue($rc2->hasMethod('setCreatedAt')); + + + // class __DDC1590User { ... } + $rc3 = new \ReflectionClass($ns.'\__DDC1590User'); + + $this->assertTrue($rc3->hasProperty('name')); + $this->assertFalse($rc3->hasProperty('id')); + $this->assertFalse($rc3->hasProperty('created_at')); + + $this->assertTrue($rc3->hasMethod('getName')); + $this->assertTrue($rc3->hasMethod('setName')); + $this->assertFalse($rc3->hasMethod('getId')); + $this->assertFalse($rc3->hasMethod('setId')); + $this->assertFalse($rc3->hasMethod('getCreatedAt')); + $this->assertFalse($rc3->hasMethod('setCreatedAt')); + } + /** * @return array */ diff --git a/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php b/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php index 7858253f1..f36ed162a 100644 --- a/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/SchemaValidatorTest.php @@ -134,6 +134,24 @@ class SchemaValidatorTest extends \Doctrine\Tests\OrmTestCase "The referenced column name 'id' has to be a primary key column on the target entity class 'Doctrine\Tests\ORM\Tools\DDC1649Two'." ), $ce); } + + /** + * @group DDC-3274 + */ + public function testInvalidBiDirectionalRelationMappingMissingInversedByAttribute() + { + $class = $this->em->getClassMetadata(__NAMESPACE__ . '\DDC3274One'); + $ce = $this->validator->validateClass($class); + + $this->assertEquals( + array( + "The field Doctrine\Tests\ORM\Tools\DDC3274One#two is on the inverse side of a bi-directional " . + "relationship, but the specified mappedBy association on the target-entity " . + "Doctrine\Tests\ORM\Tools\DDC3274Two#one does not contain the required 'inversedBy=\"two\"' attribute." + ), + $ce + ); + } } /** @@ -263,3 +281,30 @@ class DDC1649Three private $two; } +/** + * @Entity + */ +class DDC3274One +{ + /** + * @Id @Column @GeneratedValue + */ + private $id; + + /** + * @OneToMany(targetEntity="DDC3274Two", mappedBy="one") + */ + private $two; +} + +/** + * @Entity + */ +class DDC3274Two +{ + /** + * @Id + * @ManyToOne(targetEntity="DDC3274One") + */ + private $one; +} diff --git a/tests/travis/mysql.travis.xml b/tests/travis/mysql.travis.xml index 8319d1466..84c8fa1b3 100644 --- a/tests/travis/mysql.travis.xml +++ b/tests/travis/mysql.travis.xml @@ -1,5 +1,5 @@ - + diff --git a/tests/travis/pgsql.travis.xml b/tests/travis/pgsql.travis.xml index 75c831dd1..8b053576c 100644 --- a/tests/travis/pgsql.travis.xml +++ b/tests/travis/pgsql.travis.xml @@ -1,5 +1,5 @@ - + @@ -36,4 +36,4 @@ - \ No newline at end of file + diff --git a/tests/travis/sqlite.travis.xml b/tests/travis/sqlite.travis.xml index 5233adeb6..f9b3ef1f3 100644 --- a/tests/travis/sqlite.travis.xml +++ b/tests/travis/sqlite.travis.xml @@ -1,5 +1,5 @@ - + @@ -18,4 +18,4 @@ - \ No newline at end of file +