mirror of
https://github.com/doctrine/orm.git
synced 2026-04-22 22:18:04 +02:00
Compare commits
201 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5aedac1e5c | |||
| caf30b889b | |||
| 0cf7e0e628 | |||
| 2290d1ff9b | |||
| ecb1e1060a | |||
| 9dfa20d3af | |||
| 33baa41e9f | |||
| 1c8f9ca1cc | |||
| 7aa33c6a15 | |||
| 0fc476d068 | |||
| 1e38d7d07e | |||
| bac6570af1 | |||
| 18c873216b | |||
| 11936a6cac | |||
| f5705d6d95 | |||
| a1bd3e8cc9 | |||
| 2fa48c6e88 | |||
| c4ab4db743 | |||
| c6e7a81849 | |||
| 4bed15b984 | |||
| 4884183b95 | |||
| fac410b213 | |||
| cbe5575f38 | |||
| 94c0e46c96 | |||
| af59ea962f | |||
| e05930e714 | |||
| db06355b63 | |||
| 2e9ffe831c | |||
| 9d7256aace | |||
| 52b3e21969 | |||
| 97afe00d0f | |||
| 51250e987e | |||
| c4b59b4eb0 | |||
| daca81861c | |||
| 52fbe35bc7 | |||
| 50ac97e72d | |||
| cfed92a5cf | |||
| d69fd91454 | |||
| 41258deed7 | |||
| 193ec51607 | |||
| 7292920b15 | |||
| 24ebfb69cb | |||
| ff0168834e | |||
| a88550a70c | |||
| ee246af7e3 | |||
| ba04c9801d | |||
| 5d637af056 | |||
| ec84953af4 | |||
| 56c5cb41fc | |||
| e0077b290b | |||
| ee9aebf569 | |||
| 91e5c0d443 | |||
| 05342b0b94 | |||
| 8198a6ce7e | |||
| b5e40fe5f5 | |||
| ddf3125afe | |||
| 8d33ccced1 | |||
| b11ae45a2f | |||
| d3112bf119 | |||
| 4e4637de2e | |||
| 4c8abd5d83 | |||
| 71f446f23b | |||
| 2bc4ff3cab | |||
| 39f2f0eb91 | |||
| a5a7c879fc | |||
| 5670912d0d | |||
| fae0f6a29a | |||
| f45cf2629e | |||
| 4d846c1992 | |||
| 37516d7548 | |||
| 24c4ec91e5 | |||
| f31f088f0b | |||
| 51da937bbc | |||
| 801e7f0ef7 | |||
| f0e6408005 | |||
| c398f8c2c2 | |||
| 060bbb1366 | |||
| 34fad084a7 | |||
| bdc54d481c | |||
| 60462919f2 | |||
| 5a8a017a66 | |||
| c701e8b9a6 | |||
| df99353f19 | |||
| 8b5dae30a5 | |||
| 78770f9da8 | |||
| 2f57c4fef9 | |||
| 684ae859ce | |||
| 5f9dc2e5bc | |||
| 2dbe28a150 | |||
| ea3856673d | |||
| 7c02af8896 | |||
| 61c18ce046 | |||
| 7f5620a41c | |||
| ae198d5e45 | |||
| 705c33bc35 | |||
| 3cef0fdbfa | |||
| ccbe849a72 | |||
| 2b8e03ff12 | |||
| c4e93cf68c | |||
| cfdef3bf19 | |||
| 8bb1d5448b | |||
| bebacf79d8 | |||
| d46fa4adeb | |||
| 64061bafaf | |||
| a69584a841 | |||
| 8fc1c34b29 | |||
| 0d683c1897 | |||
| 60b75fefed | |||
| 0a7e0617cc | |||
| 072e1eee7b | |||
| c0d3cdbdfb | |||
| a50ae2c898 | |||
| dbbe7a4be5 | |||
| 406e177062 | |||
| fc19c3b53d | |||
| 5c5abb6771 | |||
| 42226dadd1 | |||
| 84f8ef5ca4 | |||
| 8a13376d42 | |||
| 8b5632cb65 | |||
| 859465b691 | |||
| 530c01b5e3 | |||
| 63c5758070 | |||
| 0fb236f451 | |||
| 2a9a53ae9d | |||
| 0081319712 | |||
| 78ceda7ecf | |||
| 1f4810e370 | |||
| 376a3ac3b6 | |||
| ab87dd6325 | |||
| 2ae245db30 | |||
| 9d36e855c0 | |||
| f7c87cddd8 | |||
| 1566b8a057 | |||
| 333fa1090a | |||
| 0262b083bb | |||
| 60c9c27c08 | |||
| 8b75e3563a | |||
| cbf16f1cf8 | |||
| b84c828ea1 | |||
| 55b7e4cff2 | |||
| e38af55100 | |||
| 7338c2d1f8 | |||
| 0ff3cdf150 | |||
| 24c5c54c1e | |||
| 6bb367f488 | |||
| 213cc5c695 | |||
| a949e87ca8 | |||
| f18d0e093b | |||
| 0e139055f9 | |||
| b9c6659b70 | |||
| 5c06121d94 | |||
| 5bfa56aee0 | |||
| 0363a5548d | |||
| 3764e49e6c | |||
| 6ee20204a5 | |||
| d9b0c87ded | |||
| 8594e5c4da | |||
| 5f821f3b98 | |||
| b566525099 | |||
| 215c4a03e1 | |||
| b3ccd6466b | |||
| b596bbb29f | |||
| c204e6c6a1 | |||
| 0bc94589e1 | |||
| f37856829f | |||
| 157c793810 | |||
| 72d838a804 | |||
| 58f8dc5d4c | |||
| 7d3ecd9481 | |||
| 1bb55703a7 | |||
| 56cbcec13d | |||
| 837c19bfc0 | |||
| 7b8f09ee4a | |||
| 488a4dc78a | |||
| 1364b6acc6 | |||
| 3dbe181762 | |||
| a3acaab65c | |||
| f183d25a33 | |||
| 7c8350094e | |||
| c613410ba6 | |||
| 6bb7581dd7 | |||
| ab71dab7d1 | |||
| 2c114756bd | |||
| 45496f040d | |||
| b40866c624 | |||
| a89cc7abea | |||
| 5ac111e5f8 | |||
| c5f66e6e7f | |||
| b59f495875 | |||
| 3829b9c28b | |||
| 65bcdbf4c7 | |||
| 95d000e51b | |||
| 3657df3b01 | |||
| 1661ffae9a | |||
| b424a5cf14 | |||
| 2767a4eec4 | |||
| 9486867279 | |||
| 6f2bb08972 | |||
| da2d3b406e | |||
| c4b7d3fbea |
+8
-6
@@ -4,6 +4,7 @@ php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
|
||||
env:
|
||||
- DB=mysql
|
||||
@@ -11,14 +12,15 @@ env:
|
||||
- DB=sqlite
|
||||
|
||||
before_script:
|
||||
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests;' -U postgres; fi"
|
||||
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests_tmp;' -U postgres; fi"
|
||||
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests;' -U postgres; fi"
|
||||
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests_tmp;' -U postgres; fi"
|
||||
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi"
|
||||
- if [[ $TRAVIS_PHP_VERSION = '5.6' && $DB = 'sqlite' ]]; then PHPUNIT_FLAGS="--coverage-clover ./build/logs/clover.xml"; else PHPUNIT_FLAGS=""; fi
|
||||
- if [ $DB = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests;' -U postgres; fi
|
||||
- if [ $DB = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests_tmp;' -U postgres; fi
|
||||
- if [ $DB = 'pgsql' ]; then psql -c 'create database doctrine_tests;' -U postgres; fi
|
||||
- if [ $DB = 'pgsql' ]; then psql -c 'create database doctrine_tests_tmp;' -U postgres; fi
|
||||
- if [ $DB = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi
|
||||
- composer install --prefer-dist --dev
|
||||
|
||||
script: phpunit --configuration tests/travis/$DB.travis.xml
|
||||
script: phpunit $PHPUNIT_FLAGS --configuration tests/travis/$DB.travis.xml
|
||||
|
||||
after_script:
|
||||
- php vendor/bin/coveralls -v
|
||||
|
||||
@@ -44,6 +44,12 @@ Now parenthesis are considered, the previous DQL will generate:
|
||||
|
||||
# Upgrade to 2.3
|
||||
|
||||
## Auto Discriminator Map breaks userland implementations with Listener
|
||||
|
||||
The new feature to detect discriminator maps automatically when none
|
||||
are provided breaks userland implementations doing this with a
|
||||
listener in ``loadClassMetadata`` event.
|
||||
|
||||
## EntityManager#find() not calls EntityRepository#find() anymore
|
||||
|
||||
Previous to 2.3, calling ``EntityManager#find()`` would be delegated to
|
||||
|
||||
+1
-1
Submodule docs/en/_theme updated: 68795c5888...dc294be1db
+2
-1
@@ -14,7 +14,7 @@ Doctrine ORM don't panic. You can get help from different sources:
|
||||
|
||||
- There is a :doc:`FAQ <reference/faq>` with answers to frequent questions.
|
||||
- The `Doctrine Mailing List <http://groups.google.com/group/doctrine-user>`_
|
||||
- Internet Relay Chat (IRC) in `#doctrine on Freenode <irc://irc.freenode.net/doctrine>`_
|
||||
- Internet Relay Chat (IRC) in #doctrine on Freenode
|
||||
- Report a bug on `JIRA <http://www.doctrine-project.org/jira>`_.
|
||||
- On `Twitter <https://twitter.com/search/%23doctrine2>`_ with ``#doctrine2``
|
||||
- On `StackOverflow <http://stackoverflow.com/questions/tagged/doctrine2>`_
|
||||
@@ -120,3 +120,4 @@ Cookbook
|
||||
:doc:`MySQL Enums <cookbook/mysql-enums>`
|
||||
:doc:`Advanced Field Value Conversion <cookbook/advanced-field-value-conversion-using-custom-mapping-types>`
|
||||
|
||||
.. include:: toc.rst
|
||||
|
||||
@@ -106,7 +106,7 @@ 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
|
||||
`from here <http://redis.io/>`_. Also check
|
||||
`here <https://github.com/nicolasff/phpredis/>`_ for how you can use
|
||||
`A PHP extension for Redis <https://github.com/nicolasff/phpredis/>`_ for how you can use
|
||||
and install Redis PHP extension.
|
||||
|
||||
Below is a simple example of how you could use the Redis cache
|
||||
|
||||
@@ -100,7 +100,7 @@ Doctrine ships with a number of command line tools that are very helpful
|
||||
during development. You can call this command from the Composer binary
|
||||
directory:
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: sh
|
||||
|
||||
$ php vendor/bin/doctrine
|
||||
|
||||
|
||||
@@ -207,10 +207,13 @@ listeners:
|
||||
|
||||
|
||||
- Lifecycle Callbacks are methods on the entity classes that are
|
||||
called when the event is triggered. They receives some kind of ``EventArgs``.
|
||||
called when the event is triggered. As of v2.4 they receive some kind
|
||||
of ``EventArgs`` instance.
|
||||
- Lifecycle Event Listeners and Subscribers are classes with specific callback
|
||||
methods that receives some kind of ``EventArgs`` instance which
|
||||
give access to the entity, EntityManager or other relevant data.
|
||||
methods that receives some kind of ``EventArgs`` instance.
|
||||
|
||||
The EventArgs instance received by the listener gives access to the entity,
|
||||
EntityManager and other relevant data.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -224,10 +227,11 @@ listeners:
|
||||
Lifecycle Callbacks
|
||||
-------------------
|
||||
|
||||
A lifecycle event is a regular event with the additional feature of
|
||||
providing a mechanism to register direct callbacks inside the
|
||||
corresponding entity classes that are executed when the lifecycle
|
||||
event occurs.
|
||||
Lifecycle Callbacks are defined on an entity class. They allow you to
|
||||
trigger callbacks whenever an instance of that entity class experiences
|
||||
a relevant lifecycle event. More than one callback can be defined for each
|
||||
lifecycle event. Lifecycle Callbacks are best used for simple operations
|
||||
specific to a particular entity class's lifecycle.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -277,8 +281,9 @@ event occurs.
|
||||
}
|
||||
}
|
||||
|
||||
Note that when using annotations you have to apply the
|
||||
@HasLifecycleCallbacks marker annotation on the entity class.
|
||||
Note that the methods set as lifecycle callbacks need to be public and,
|
||||
when using these annotations, you have to apply the
|
||||
``@HasLifecycleCallbacks`` marker annotation on the entity class.
|
||||
|
||||
If you want to register lifecycle callbacks from YAML or XML you
|
||||
can do it with the following.
|
||||
@@ -295,6 +300,10 @@ can do it with the following.
|
||||
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
|
||||
postPersist: [ doStuffOnPostPersist ]
|
||||
|
||||
In YAML the ``key`` of the lifecycleCallbacks entry is the event that you
|
||||
are triggering on and the value is the method (or methods) to call. The allowed
|
||||
event types are the ones listed in the previous Lifecycle Events section.
|
||||
|
||||
XML would look something like this:
|
||||
|
||||
.. code-block:: xml
|
||||
@@ -317,9 +326,14 @@ XML would look something like this:
|
||||
|
||||
</doctrine-mapping>
|
||||
|
||||
You just need to make sure a public ``doStuffOnPrePersist()`` and
|
||||
``doStuffOnPostPersist()`` method is defined on your ``User``
|
||||
model.
|
||||
In XML the ``type`` of the lifecycle-callback entry is the event that you
|
||||
are triggering on and the ``method`` is the method to call. The allowed event
|
||||
types are the ones listed in the previous Lifecycle Events section.
|
||||
|
||||
When using YAML or XML you need to remember to create public methods to match the
|
||||
callback names you defined. E.g. in these examples ``doStuffOnPrePersist()``,
|
||||
``doOtherStuffOnPrePersist()`` and ``doStuffOnPostPersist()`` methods need to be
|
||||
defined on your ``User`` model.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -375,8 +389,10 @@ Listening and subscribing to Lifecycle Events
|
||||
|
||||
Lifecycle event listeners are much more powerful than the simple
|
||||
lifecycle callbacks that are defined on the entity classes. They
|
||||
allow to implement re-usable behaviors between different entity
|
||||
classes, yet require much more detailed knowledge about the inner
|
||||
sit at a level above the entities and allow you to implement re-usable
|
||||
behaviors across different entity classes.
|
||||
|
||||
Note that they require much more detailed knowledge about the inner
|
||||
workings of the EntityManager and UnitOfWork. Please read the
|
||||
*Implementing Event Listeners* section carefully if you are trying
|
||||
to write your own listener.
|
||||
@@ -476,8 +492,8 @@ data and lost updates/persists/removes.
|
||||
|
||||
For the described events that are also lifecycle callback events
|
||||
the restrictions apply as well, with the additional restriction
|
||||
that you do not have access to the EntityManager or UnitOfWork APIs
|
||||
inside these events.
|
||||
that (prior to version 2.4) you do not have access to the
|
||||
EntityManager or UnitOfWork APIs inside these events.
|
||||
|
||||
prePersist
|
||||
~~~~~~~~~~
|
||||
@@ -501,11 +517,9 @@ The following restrictions apply to ``prePersist``:
|
||||
- If you are using a PrePersist Identity Generator such as
|
||||
sequences the ID value will *NOT* be available within any
|
||||
PrePersist events.
|
||||
- Doctrine will not recognize changes made to relations in a pre
|
||||
persist event called by "reachability" through a cascade persist
|
||||
unless you use the internal ``UnitOfWork`` API. We do not recommend
|
||||
such operations in the persistence by reachability context, so do
|
||||
this at your own risk and possibly supported by unit-tests.
|
||||
- Doctrine will not recognize changes made to relations in a prePersist
|
||||
event. This includes modifications to
|
||||
collections such as additions, removals or replacement.
|
||||
|
||||
preRemove
|
||||
~~~~~~~~~
|
||||
@@ -699,7 +713,8 @@ Restrictions for this event:
|
||||
recognized by the flush operation anymore.
|
||||
- Changes to fields of the passed entities are not recognized by
|
||||
the flush operation anymore, use the computed change-set passed to
|
||||
the event to modify primitive field values.
|
||||
the event to modify primitive field values, e.g. use
|
||||
``$eventArgs->setNewValue($field, $value);`` as in the Alice to Bob example above.
|
||||
- Any calls to ``EntityManager#persist()`` or
|
||||
``EntityManager#remove()``, even in combination with the UnitOfWork
|
||||
API are strongly discouraged and don't work as expected outside the
|
||||
@@ -769,9 +784,10 @@ An ``Entity Listener`` could be any class, by default it should be a class with
|
||||
|
||||
- Different from :ref:`reference-events-implementing-listeners` an ``Entity Listener`` is invoked just to the specified entity
|
||||
- An entity listener method receives two arguments, the entity instance and the lifecycle event.
|
||||
- A callback method could be defined by naming convention or specifying a method mapping.
|
||||
- When the listener mapping is not given the parser will lookup for methods that match with the naming convention.
|
||||
- When the listener mapping is given the parser won't lookup for any naming convention.
|
||||
- The callback method can be defined by naming convention or specifying a method mapping.
|
||||
- When a listener mapping is not given the parser will use the naming convention to look for a matching method,
|
||||
e.g. it will look for a public ``preUpdate()`` method if you are listening to the ``preUpdate`` event.
|
||||
- When a listener mapping is given the parser will not look for any methods using the naming convention.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ See the documentation chapter on :doc:`inheritance mapping <inheritance-mapping>
|
||||
the details.
|
||||
|
||||
Why does Doctrine not create proxy objects for my inheritance hierarchy?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you set a many-to-one or one-to-one association target-entity to any parent class of
|
||||
an inheritance hierarchy Doctrine does not know what PHP class the foreign is actually of.
|
||||
|
||||
+8
-4
@@ -8,12 +8,14 @@ Tutorials
|
||||
:maxdepth: 1
|
||||
|
||||
tutorials/getting-started
|
||||
tutorials/getting-started-database
|
||||
tutorials/getting-started-models
|
||||
tutorials/working-with-indexed-associations
|
||||
tutorials/extra-lazy-associations
|
||||
tutorials/composite-primary-keys
|
||||
tutorials/ordered-associations
|
||||
tutorials/in-ten-quick-steps
|
||||
tutorials/override-field-association-mappings-in-subclasses
|
||||
tutorials/pagination.rst
|
||||
|
||||
Reference Guide
|
||||
---------------
|
||||
@@ -22,9 +24,9 @@ Reference Guide
|
||||
:maxdepth: 1
|
||||
:numbered:
|
||||
|
||||
reference/introduction
|
||||
reference/architecture
|
||||
reference/configuration
|
||||
reference/installation
|
||||
reference/configuration.rst
|
||||
reference/faq
|
||||
reference/basic-mapping
|
||||
reference/association-mapping
|
||||
@@ -51,9 +53,9 @@ Reference Guide
|
||||
reference/metadata-drivers
|
||||
reference/best-practices
|
||||
reference/limitations-and-known-issues
|
||||
tutorials/pagination.rst
|
||||
reference/filters.rst
|
||||
reference/namingstrategy.rst
|
||||
reference/advanced-configuration.rst
|
||||
|
||||
|
||||
Cookbook
|
||||
@@ -63,6 +65,7 @@ Cookbook
|
||||
:maxdepth: 1
|
||||
|
||||
cookbook/aggregate-fields
|
||||
cookbook/custom-mapping-types
|
||||
cookbook/decorator-pattern
|
||||
cookbook/dql-custom-walkers
|
||||
cookbook/dql-user-defined-functions
|
||||
@@ -70,6 +73,7 @@ Cookbook
|
||||
cookbook/implementing-the-notify-changetracking-policy
|
||||
cookbook/implementing-wakeup-or-clone
|
||||
cookbook/integrating-with-codeigniter
|
||||
cookbook/resolve-target-entity-listener
|
||||
cookbook/sql-table-prefixes
|
||||
cookbook/strategy-cookbook-introduction
|
||||
cookbook/validation-of-entities
|
||||
|
||||
@@ -350,6 +350,7 @@
|
||||
<xs:element name="generator" type="orm:generator" minOccurs="0" />
|
||||
<xs:element name="sequence-generator" type="orm:sequence-generator" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="custom-id-generator" type="orm:custom-id-generator" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="options" type="orm:options" minOccurs="0" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
|
||||
@@ -165,9 +165,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the database connection object used by the EntityManager.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Connection
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
@@ -185,18 +183,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an ExpressionBuilder used for object-oriented construction of query expressions.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <code>
|
||||
* $qb = $em->createQueryBuilder();
|
||||
* $expr = $em->getExpressionBuilder();
|
||||
* $qb->select('u')->from('User', 'u')
|
||||
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
|
||||
* </code>
|
||||
*
|
||||
* @return \Doctrine\ORM\Query\Expr
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getExpressionBuilder()
|
||||
{
|
||||
@@ -208,9 +195,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a transaction on the underlying database connection.
|
||||
*
|
||||
* @return void
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function beginTransaction()
|
||||
{
|
||||
@@ -218,18 +203,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a function in a transaction.
|
||||
*
|
||||
* The function gets passed this EntityManager instance as an (optional) parameter.
|
||||
*
|
||||
* {@link flush} is invoked prior to transaction commit.
|
||||
*
|
||||
* If an exception occurs during execution of the function or flushing or transaction commit,
|
||||
* the transaction is rolled back, the EntityManager closed and the exception re-thrown.
|
||||
*
|
||||
* @param callable $func The function to execute transactionally.
|
||||
*
|
||||
* @return mixed The non-empty value returned from the closure or true instead.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function transactional($func)
|
||||
{
|
||||
@@ -255,9 +229,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits a transaction on the underlying database connection.
|
||||
*
|
||||
* @return void
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
@@ -265,9 +237,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a rollback on the underlying database connection.
|
||||
*
|
||||
* @return void
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
@@ -296,11 +266,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Query object.
|
||||
*
|
||||
* @param string $dql The DQL string.
|
||||
*
|
||||
* @return \Doctrine\ORM\Query
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createQuery($dql = '')
|
||||
{
|
||||
@@ -314,11 +280,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Query from a named query.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return \Doctrine\ORM\Query
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createNamedQuery($name)
|
||||
{
|
||||
@@ -326,12 +288,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a native SQL query.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param ResultSetMapping $rsm The ResultSetMapping to use.
|
||||
*
|
||||
* @return NativeQuery
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createNativeQuery($sql, ResultSetMapping $rsm)
|
||||
{
|
||||
@@ -344,11 +301,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a NativeQuery from a named native query.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return \Doctrine\ORM\NativeQuery
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createNamedNativeQuery($name)
|
||||
{
|
||||
@@ -358,9 +311,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a QueryBuilder instance
|
||||
*
|
||||
* @return QueryBuilder
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function createQueryBuilder()
|
||||
{
|
||||
@@ -480,15 +431,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the entity identified by the given type and identifier
|
||||
* without actually loading it, if the entity is not yet loaded.
|
||||
*
|
||||
* @param string $entityName The name of the entity type.
|
||||
* @param mixed $id The entity identifier.
|
||||
*
|
||||
* @return object The entity reference.
|
||||
*
|
||||
* @throws ORMException
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getReference($entityName, $id)
|
||||
{
|
||||
@@ -529,24 +472,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a partial reference to the entity identified by the given type and identifier
|
||||
* without actually loading it, if the entity is not yet loaded.
|
||||
*
|
||||
* The returned reference may be a partial object if the entity is not yet loaded/managed.
|
||||
* If it is a partial object it will not initialize the rest of the entity state on access.
|
||||
* Thus you can only ever safely access the identifier of an entity obtained through
|
||||
* this method.
|
||||
*
|
||||
* The use-cases for partial references involve maintaining bidirectional associations
|
||||
* without loading one side of the association or to update an entity without loading it.
|
||||
* Note, however, that in the latter case the original (persistent) entity data will
|
||||
* never be visible to the application (especially not event listeners) as it will
|
||||
* never be loaded in the first place.
|
||||
*
|
||||
* @param string $entityName The name of the entity type.
|
||||
* @param mixed $identifier The entity identifier.
|
||||
*
|
||||
* @return object The (partial) entity reference.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getPartialReference($entityName, $identifier)
|
||||
{
|
||||
@@ -585,11 +511,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the EntityManager. All entities that are currently managed
|
||||
* by this EntityManager become detached. The EntityManager may no longer
|
||||
* be used after it is closed.
|
||||
*
|
||||
* @return void
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
@@ -713,14 +635,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of the given entity. Can create a shallow or a deep copy.
|
||||
*
|
||||
* @param object $entity The entity to copy.
|
||||
* @param boolean $deep FALSE for a shallow copy, TRUE for a deep copy.
|
||||
*
|
||||
* @return object The new entity.
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @todo Implementation need. This is necessary since $e2 = clone $e1; throws an E_FATAL when access anything on $e:
|
||||
* Fatal error: Maximum function nesting level of '100' reached, aborting!
|
||||
@@ -731,16 +646,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquire a lock on the given entity.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param int $lockMode
|
||||
* @param int|null $lockVersion
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws OptimisticLockException
|
||||
* @throws PessimisticLockException
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function lock($entity, $lockMode, $lockVersion = null)
|
||||
{
|
||||
@@ -774,9 +680,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EventManager used by the EntityManager.
|
||||
*
|
||||
* @return \Doctrine\Common\EventManager
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getEventManager()
|
||||
{
|
||||
@@ -784,9 +688,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Configuration used by the EntityManager.
|
||||
*
|
||||
* @return \Doctrine\ORM\Configuration
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getConfiguration()
|
||||
{
|
||||
@@ -808,9 +710,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Entity manager is open or closed.
|
||||
*
|
||||
* @return bool
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isOpen()
|
||||
{
|
||||
@@ -818,9 +718,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the UnitOfWork used by the EntityManager to coordinate operations.
|
||||
*
|
||||
* @return \Doctrine\ORM\UnitOfWork
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getUnitOfWork()
|
||||
{
|
||||
@@ -828,16 +726,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a hydrator for the given hydration mode.
|
||||
*
|
||||
* This method caches the hydrator instances which is used for all queries that don't
|
||||
* selectively iterate over the result.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param int $hydrationMode
|
||||
*
|
||||
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getHydrator($hydrationMode)
|
||||
{
|
||||
@@ -845,13 +734,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance for the given hydration mode.
|
||||
*
|
||||
* @param int $hydrationMode
|
||||
*
|
||||
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
*
|
||||
* @throws ORMException
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function newHydrator($hydrationMode)
|
||||
{
|
||||
@@ -881,9 +764,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the proxy factory used by the EntityManager to create entity proxies.
|
||||
*
|
||||
* @return ProxyFactory
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getProxyFactory()
|
||||
{
|
||||
@@ -891,13 +772,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to initialize a lazy loading proxy or persistent collection.
|
||||
*
|
||||
* This method is a no-op for other objects
|
||||
*
|
||||
* @param object $obj
|
||||
*
|
||||
* @return void
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function initializeObject($obj)
|
||||
{
|
||||
@@ -943,9 +818,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enabled filters.
|
||||
*
|
||||
* @return FilterCollection The active filter collection.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
@@ -957,9 +830,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the state of the filter collection is clean.
|
||||
*
|
||||
* @return boolean True, if the filter collection is clean.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isFiltersStateClean()
|
||||
{
|
||||
@@ -967,9 +838,7 @@ use Doctrine\Common\Util\ClassUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the Entity Manager has filters.
|
||||
*
|
||||
* @return boolean True, if the EM has a filter collection.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function hasFilters()
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\DBAL\LockMode;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
|
||||
/**
|
||||
@@ -31,30 +30,258 @@ use Doctrine\ORM\Query\ResultSetMapping;
|
||||
*/
|
||||
interface EntityManagerInterface extends ObjectManager
|
||||
{
|
||||
/**
|
||||
* Gets the database connection object used by the EntityManager.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Connection
|
||||
*/
|
||||
public function getConnection();
|
||||
|
||||
/**
|
||||
* Gets an ExpressionBuilder used for object-oriented construction of query expressions.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <code>
|
||||
* $qb = $em->createQueryBuilder();
|
||||
* $expr = $em->getExpressionBuilder();
|
||||
* $qb->select('u')->from('User', 'u')
|
||||
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
|
||||
* </code>
|
||||
*
|
||||
* @return \Doctrine\ORM\Query\Expr
|
||||
*/
|
||||
public function getExpressionBuilder();
|
||||
|
||||
/**
|
||||
* Starts a transaction on the underlying database connection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function beginTransaction();
|
||||
|
||||
/**
|
||||
* Executes a function in a transaction.
|
||||
*
|
||||
* The function gets passed this EntityManager instance as an (optional) parameter.
|
||||
*
|
||||
* {@link flush} is invoked prior to transaction commit.
|
||||
*
|
||||
* If an exception occurs during execution of the function or flushing or transaction commit,
|
||||
* the transaction is rolled back, the EntityManager closed and the exception re-thrown.
|
||||
*
|
||||
* @param callable $func The function to execute transactionally.
|
||||
*
|
||||
* @return mixed The non-empty value returned from the closure or true instead.
|
||||
*/
|
||||
public function transactional($func);
|
||||
|
||||
/**
|
||||
* Commits a transaction on the underlying database connection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function commit();
|
||||
|
||||
/**
|
||||
* Performs a rollback on the underlying database connection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function rollback();
|
||||
|
||||
/**
|
||||
* Creates a new Query object.
|
||||
*
|
||||
* @param string $dql The DQL string.
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
public function createQuery($dql = '');
|
||||
|
||||
/**
|
||||
* Creates a Query from a named query.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
public function createNamedQuery($name);
|
||||
|
||||
/**
|
||||
* Creates a native SQL query.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param ResultSetMapping $rsm The ResultSetMapping to use.
|
||||
*
|
||||
* @return NativeQuery
|
||||
*/
|
||||
public function createNativeQuery($sql, ResultSetMapping $rsm);
|
||||
|
||||
/**
|
||||
* Creates a NativeQuery from a named native query.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return NativeQuery
|
||||
*/
|
||||
public function createNamedNativeQuery($name);
|
||||
|
||||
/**
|
||||
* Create a QueryBuilder instance
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function createQueryBuilder();
|
||||
|
||||
/**
|
||||
* Gets a reference to the entity identified by the given type and identifier
|
||||
* without actually loading it, if the entity is not yet loaded.
|
||||
*
|
||||
* @param string $entityName The name of the entity type.
|
||||
* @param mixed $id The entity identifier.
|
||||
*
|
||||
* @return object The entity reference.
|
||||
*
|
||||
* @throws ORMException
|
||||
*/
|
||||
public function getReference($entityName, $id);
|
||||
|
||||
/**
|
||||
* Gets a partial reference to the entity identified by the given type and identifier
|
||||
* without actually loading it, if the entity is not yet loaded.
|
||||
*
|
||||
* The returned reference may be a partial object if the entity is not yet loaded/managed.
|
||||
* If it is a partial object it will not initialize the rest of the entity state on access.
|
||||
* Thus you can only ever safely access the identifier of an entity obtained through
|
||||
* this method.
|
||||
*
|
||||
* The use-cases for partial references involve maintaining bidirectional associations
|
||||
* without loading one side of the association or to update an entity without loading it.
|
||||
* Note, however, that in the latter case the original (persistent) entity data will
|
||||
* never be visible to the application (especially not event listeners) as it will
|
||||
* never be loaded in the first place.
|
||||
*
|
||||
* @param string $entityName The name of the entity type.
|
||||
* @param mixed $identifier The entity identifier.
|
||||
*
|
||||
* @return object The (partial) entity reference.
|
||||
*/
|
||||
public function getPartialReference($entityName, $identifier);
|
||||
|
||||
/**
|
||||
* Closes the EntityManager. All entities that are currently managed
|
||||
* by this EntityManager become detached. The EntityManager may no longer
|
||||
* be used after it is closed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close();
|
||||
|
||||
/**
|
||||
* Creates a copy of the given entity. Can create a shallow or a deep copy.
|
||||
*
|
||||
* @param object $entity The entity to copy.
|
||||
* @param boolean $deep FALSE for a shallow copy, TRUE for a deep copy.
|
||||
*
|
||||
* @return object The new entity.
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function copy($entity, $deep = false);
|
||||
|
||||
/**
|
||||
* Acquire a lock on the given entity.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param int $lockMode
|
||||
* @param int|null $lockVersion
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws OptimisticLockException
|
||||
* @throws PessimisticLockException
|
||||
*/
|
||||
public function lock($entity, $lockMode, $lockVersion = null);
|
||||
|
||||
/**
|
||||
* Gets the EventManager used by the EntityManager.
|
||||
*
|
||||
* @return \Doctrine\Common\EventManager
|
||||
*/
|
||||
public function getEventManager();
|
||||
|
||||
/**
|
||||
* Gets the Configuration used by the EntityManager.
|
||||
*
|
||||
* @return Configuration
|
||||
*/
|
||||
public function getConfiguration();
|
||||
|
||||
/**
|
||||
* Check if the Entity manager is open or closed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isOpen();
|
||||
|
||||
/**
|
||||
* Gets the UnitOfWork used by the EntityManager to coordinate operations.
|
||||
*
|
||||
* @return UnitOfWork
|
||||
*/
|
||||
public function getUnitOfWork();
|
||||
|
||||
/**
|
||||
* Gets a hydrator for the given hydration mode.
|
||||
*
|
||||
* This method caches the hydrator instances which is used for all queries that don't
|
||||
* selectively iterate over the result.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param int $hydrationMode
|
||||
*
|
||||
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
*/
|
||||
public function getHydrator($hydrationMode);
|
||||
|
||||
/**
|
||||
* Create a new instance for the given hydration mode.
|
||||
*
|
||||
* @param int $hydrationMode
|
||||
*
|
||||
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
*
|
||||
* @throws ORMException
|
||||
*/
|
||||
public function newHydrator($hydrationMode);
|
||||
|
||||
/**
|
||||
* Gets the proxy factory used by the EntityManager to create entity proxies.
|
||||
*
|
||||
* @return \Doctrine\ORM\Proxy\ProxyFactory
|
||||
*/
|
||||
public function getProxyFactory();
|
||||
|
||||
/**
|
||||
* Gets the enabled filters.
|
||||
*
|
||||
* @return \Doctrine\ORM\Query\FilterCollection The active filter collection.
|
||||
*/
|
||||
public function getFilters();
|
||||
|
||||
/**
|
||||
* Checks whether the state of the filter collection is clean.
|
||||
*
|
||||
* @return boolean True, if the filter collection is clean.
|
||||
*/
|
||||
public function isFiltersStateClean();
|
||||
|
||||
/**
|
||||
* Checks whether the Entity Manager has filters.
|
||||
*
|
||||
* @return boolean True, if the EM has a filter collection.
|
||||
*/
|
||||
public function hasFilters();
|
||||
}
|
||||
|
||||
@@ -88,4 +88,18 @@ class HydrationException extends \Doctrine\ORM\ORMException
|
||||
$discrColumnName, $entityName, $dqlAlias
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $discrValue
|
||||
* @param array $discrMap
|
||||
*
|
||||
* @return HydrationException
|
||||
*/
|
||||
public static function invalidDiscriminatorValue($discrValue, $discrMap)
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The discriminator value "%s" is invalid. It must be one of "%s".',
|
||||
$discrValue, implode('", "', $discrMap)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,7 +266,13 @@ class ObjectHydrator extends AbstractHydrator
|
||||
throw HydrationException::emptyDiscriminatorValue($dqlAlias);
|
||||
}
|
||||
|
||||
$className = $this->ce[$className]->discriminatorMap[$data[$discrColumn]];
|
||||
$discrMap = $this->ce[$className]->discriminatorMap;
|
||||
|
||||
if ( ! isset($discrMap[$data[$discrColumn]])) {
|
||||
throw HydrationException::invalidDiscriminatorValue($data[$discrColumn], array_keys($discrMap));
|
||||
}
|
||||
|
||||
$className = $discrMap[$data[$discrColumn]];
|
||||
|
||||
unset($data[$discrColumn]);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,13 @@ class SimpleObjectHydrator extends AbstractHydrator
|
||||
throw HydrationException::emptyDiscriminatorValue(key($this->_rsm->aliasMap));
|
||||
}
|
||||
|
||||
$entityName = $this->class->discriminatorMap[$sqlResult[$discrColumnName]];
|
||||
$discrMap = $this->class->discriminatorMap;
|
||||
|
||||
if ( ! isset($discrMap[$sqlResult[$discrColumnName]])) {
|
||||
throw HydrationException::invalidDiscriminatorValue($sqlResult[$discrColumnName], array_keys($discrMap));
|
||||
}
|
||||
|
||||
$entityName = $discrMap[$sqlResult[$discrColumnName]];
|
||||
|
||||
unset($sqlResult[$discrColumnName]);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,6 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
protected function initialize()
|
||||
{
|
||||
$this->driver = $this->em->getConfiguration()->getMetadataDriverImpl();
|
||||
$this->targetPlatform = $this->em->getConnection()->getDatabasePlatform();
|
||||
$this->evm = $this->em->getEventManager();
|
||||
$this->initialized = true;
|
||||
}
|
||||
@@ -432,9 +431,9 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
{
|
||||
$idGenType = $class->generatorType;
|
||||
if ($idGenType == ClassMetadata::GENERATOR_TYPE_AUTO) {
|
||||
if ($this->targetPlatform->prefersSequences()) {
|
||||
if ($this->getTargetPlatform()->prefersSequences()) {
|
||||
$class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_SEQUENCE);
|
||||
} else if ($this->targetPlatform->prefersIdentityColumns()) {
|
||||
} else if ($this->getTargetPlatform()->prefersIdentityColumns()) {
|
||||
$class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_IDENTITY);
|
||||
} else {
|
||||
$class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_TABLE);
|
||||
@@ -450,19 +449,23 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
$sequenceName = null;
|
||||
$fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null;
|
||||
|
||||
if ($this->targetPlatform instanceof Platforms\PostgreSQLPlatform) {
|
||||
if ($this->getTargetPlatform() instanceof Platforms\PostgreSQLPlatform) {
|
||||
$columnName = $class->getSingleIdentifierColumnName();
|
||||
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
|
||||
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
|
||||
$definition = array(
|
||||
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName)
|
||||
'sequenceName' => $this->getTargetPlatform()->fixSchemaElementName($sequenceName)
|
||||
);
|
||||
|
||||
if ($quoted) {
|
||||
$definition['quoted'] = true;
|
||||
}
|
||||
|
||||
$sequenceName = $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform);
|
||||
$sequenceName = $this
|
||||
->em
|
||||
->getConfiguration()
|
||||
->getQuoteStrategy()
|
||||
->getSequenceName($definition, $class, $this->getTargetPlatform());
|
||||
}
|
||||
|
||||
$generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint')
|
||||
@@ -483,7 +486,7 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
|
||||
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
|
||||
$definition = array(
|
||||
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName),
|
||||
'sequenceName' => $this->getTargetPlatform()->fixSchemaElementName($sequenceName),
|
||||
'allocationSize' => 1,
|
||||
'initialValue' => 1,
|
||||
);
|
||||
@@ -496,7 +499,7 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
}
|
||||
|
||||
$sequenceGenerator = new \Doctrine\ORM\Id\SequenceGenerator(
|
||||
$this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform),
|
||||
$this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->getTargetPlatform()),
|
||||
$definition['allocationSize']
|
||||
);
|
||||
$class->setIdGenerator($sequenceGenerator);
|
||||
@@ -569,4 +572,16 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
{
|
||||
return isset($class->isMappedSuperclass) && $class->isMappedSuperclass === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Platforms\AbstractPlatform
|
||||
*/
|
||||
private function getTargetPlatform()
|
||||
{
|
||||
if (!$this->targetPlatform) {
|
||||
$this->targetPlatform = $this->em->getConnection()->getDatabasePlatform();
|
||||
}
|
||||
|
||||
return $this->targetPlatform;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -866,7 +866,11 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
public function newInstance()
|
||||
{
|
||||
if ($this->_prototype === null) {
|
||||
$this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
|
||||
if (PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513 || PHP_VERSION_ID >= 50600) {
|
||||
$this->_prototype = $this->reflClass->newInstanceWithoutConstructor();
|
||||
} else {
|
||||
$this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
|
||||
}
|
||||
}
|
||||
|
||||
return clone $this->_prototype;
|
||||
@@ -1031,9 +1035,14 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
*/
|
||||
public function isIdentifier($fieldName)
|
||||
{
|
||||
if ( ! $this->identifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->isIdentifierComposite) {
|
||||
return $fieldName === $this->identifier[0];
|
||||
}
|
||||
|
||||
return in_array($fieldName, $this->identifier);
|
||||
}
|
||||
|
||||
@@ -2483,6 +2492,10 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
*/
|
||||
public function addLifecycleCallback($callback, $event)
|
||||
{
|
||||
if(isset($this->lifecycleCallbacks[$event]) && in_array($callback, $this->lifecycleCallbacks[$event])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->lifecycleCallbacks[$event][] = $callback;
|
||||
}
|
||||
|
||||
|
||||
@@ -450,12 +450,9 @@ class AnnotationDriver extends AbstractAnnotationDriver
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\HasLifecycleCallbacks'])) {
|
||||
/* @var $method \ReflectionMethod */
|
||||
foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
|
||||
// filter for the declaring class only, callbacks from parents will already be registered.
|
||||
if ($method->getDeclaringClass()->name !== $class->name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($this->getMethodCallbacks($method) as $value) {
|
||||
|
||||
$metadata->addLifecycleCallback($value[0], $value[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +278,10 @@ class XmlDriver extends FileDriver
|
||||
$mapping['columnDefinition'] = (string)$idElement['column-definition'];
|
||||
}
|
||||
|
||||
if (isset($idElement->options)) {
|
||||
$mapping['options'] = $this->_parseOptions($idElement->options->children());
|
||||
}
|
||||
|
||||
$metadata->mapField($mapping);
|
||||
|
||||
if (isset($idElement->generator)) {
|
||||
|
||||
@@ -416,7 +416,7 @@ class BasicEntityPersister
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$params[] = $value;
|
||||
$set[] = $column . ' = ' . $placeholder;
|
||||
$types[] = $this->columnTypes[$columnName];
|
||||
@@ -850,7 +850,7 @@ class BasicEntityPersister
|
||||
$sql = $this->getSelectSQL($id, null, $lockMode);
|
||||
list($params, $types) = $this->expandParameters($id);
|
||||
$stmt = $this->conn->executeQuery($sql, $params, $types);
|
||||
|
||||
|
||||
$hydrator = $this->em->newHydrator(Query::HYDRATE_OBJECT);
|
||||
$hydrator->hydrateAll($stmt, $this->rsm, array(Query::HINT_REFRESH => true));
|
||||
}
|
||||
@@ -1130,7 +1130,7 @@ class BasicEntityPersister
|
||||
$tableName = $this->quoteStrategy->getTableName($this->class, $this->platform);
|
||||
|
||||
if ('' !== $filterSql) {
|
||||
$conditionSql = $conditionSql
|
||||
$conditionSql = $conditionSql
|
||||
? $conditionSql . ' AND ' . $filterSql
|
||||
: $filterSql;
|
||||
}
|
||||
@@ -1283,7 +1283,7 @@ class BasicEntityPersister
|
||||
if ($assoc['isOwningSide']) {
|
||||
$tableAlias = $this->getSQLTableAlias($association['targetEntity'], $assocAlias);
|
||||
$this->selectJoinSql .= ' ' . $this->getJoinSQLForJoinColumns($association['joinColumns']);
|
||||
|
||||
|
||||
foreach ($association['joinColumns'] as $joinColumn) {
|
||||
$sourceCol = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
|
||||
$targetCol = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->class, $this->platform);
|
||||
@@ -1415,7 +1415,7 @@ class BasicEntityPersister
|
||||
foreach ($columns as $column) {
|
||||
$placeholder = '?';
|
||||
|
||||
if (isset($this->class->fieldNames[$column])
|
||||
if (isset($this->class->fieldNames[$column])
|
||||
&& isset($this->columnTypes[$this->class->fieldNames[$column]])
|
||||
&& isset($this->class->fieldMappings[$this->class->fieldNames[$column]]['requireSQLConversion'])) {
|
||||
|
||||
@@ -1488,7 +1488,7 @@ class BasicEntityPersister
|
||||
$columnName = $this->quoteStrategy->getColumnName($field, $class, $this->platform);
|
||||
$sql = $tableAlias . '.' . $columnName;
|
||||
$columnAlias = $this->getSQLColumnAlias($class->columnNames[$field]);
|
||||
|
||||
|
||||
$this->rsm->addFieldResult($alias, $columnAlias, $field);
|
||||
|
||||
if (isset($class->fieldMappings[$field]['requireSQLConversion'])) {
|
||||
@@ -1550,7 +1550,7 @@ class BasicEntityPersister
|
||||
break;
|
||||
}
|
||||
|
||||
$lock = $this->platform->appendLockHint($this->getLockTablesSql(), $lockMode);
|
||||
$lock = $this->getLockTablesSql($lockMode);
|
||||
$where = ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ';
|
||||
$sql = 'SELECT 1 '
|
||||
. $lock
|
||||
@@ -1565,13 +1565,18 @@ class BasicEntityPersister
|
||||
/**
|
||||
* Gets the FROM and optionally JOIN conditions to lock the entity managed by this persister.
|
||||
*
|
||||
* @param integer $lockMode One of the Doctrine\DBAL\LockMode::* constants.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getLockTablesSql()
|
||||
protected function getLockTablesSql($lockMode)
|
||||
{
|
||||
return 'FROM '
|
||||
. $this->quoteStrategy->getTableName($this->class, $this->platform) . ' '
|
||||
. $this->getSQLTableAlias($this->class->name);
|
||||
return $this->platform->appendLockHint(
|
||||
'FROM '
|
||||
. $this->quoteStrategy->getTableName($this->class, $this->platform) . ' '
|
||||
. $this->getSQLTableAlias($this->class->name),
|
||||
$lockMode
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1910,7 +1915,7 @@ class BasicEntityPersister
|
||||
$alias = $this->getSQLTableAlias($this->class->name);
|
||||
|
||||
$sql = 'SELECT 1 '
|
||||
. $this->getLockTablesSql()
|
||||
. $this->getLockTablesSql(null)
|
||||
. ' WHERE ' . $this->getSelectConditionSQL($criteria);
|
||||
|
||||
if ($filterSql = $this->generateFilterConditionSQL($this->class, $alias)) {
|
||||
|
||||
@@ -288,7 +288,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
foreach ($this->class->parentClasses as $parentClass) {
|
||||
$parentMetadata = $this->em->getClassMetadata($parentClass);
|
||||
$parentTable = $this->quoteStrategy->getTableName($parentMetadata, $this->platform);
|
||||
|
||||
|
||||
$this->conn->delete($parentTable, $id);
|
||||
}
|
||||
}
|
||||
@@ -342,7 +342,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
|
||||
// If the current class in the root entity, add the filters
|
||||
if ($filterSql = $this->generateFilterConditionSQL($this->em->getClassMetadata($this->class->rootEntityName), $this->getSQLTableAlias($this->class->rootEntityName))) {
|
||||
$conditionSql .= $conditionSql
|
||||
$conditionSql .= $conditionSql
|
||||
? ' AND ' . $filterSql
|
||||
: $filterSql;
|
||||
}
|
||||
@@ -387,16 +387,13 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the FROM and optionally JOIN conditions to lock the entity managed by this persister.
|
||||
*
|
||||
* @return string
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLockTablesSql()
|
||||
protected function getLockTablesSql($lockMode)
|
||||
{
|
||||
$joinSql = '';
|
||||
$identifierColumns = $this->class->getIdentifierColumnNames();
|
||||
$baseTableAlias = $this->getSQLTableAlias($this->class->name);
|
||||
$quotedTableName = $this->quoteStrategy->getTableName($this->class, $this->platform);
|
||||
|
||||
// INNER JOIN parent tables
|
||||
foreach ($this->class->parentClasses as $parentClassName) {
|
||||
@@ -412,7 +409,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
$joinSql .= implode(' AND ', $conditions);
|
||||
}
|
||||
|
||||
return 'FROM ' . $quotedTableName . ' ' . $baseTableAlias . $joinSql;
|
||||
return parent::getLockTablesSql($lockMode) . $joinSql;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -488,8 +485,8 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
|
||||
// Add join columns (foreign keys)
|
||||
foreach ($subClass->associationMappings as $mapping) {
|
||||
if ( ! $mapping['isOwningSide']
|
||||
|| ! ($mapping['type'] & ClassMetadata::TO_ONE)
|
||||
if ( ! $mapping['isOwningSide']
|
||||
|| ! ($mapping['type'] & ClassMetadata::TO_ONE)
|
||||
|| isset($mapping['inherited'])) {
|
||||
continue;
|
||||
}
|
||||
@@ -505,17 +502,17 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
}
|
||||
|
||||
$this->selectColumnListSql = implode(', ', $columnList);
|
||||
|
||||
|
||||
return $this->selectColumnListSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getInsertColumnList()
|
||||
{
|
||||
// Identifier columns must always come first in the column list of subclasses.
|
||||
$columns = $this->class->parentClasses
|
||||
$columns = $this->class->parentClasses
|
||||
? $this->class->getIdentifierColumnNames()
|
||||
: array();
|
||||
|
||||
|
||||
@@ -222,6 +222,13 @@ class OneToManyPersister extends AbstractCollectionPersister
|
||||
*/
|
||||
public function removeElement(PersistentCollection $coll, $element)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
|
||||
if ( ! $mapping['orphanRemoval']) {
|
||||
// no-op: this is not the owning side, therefore no operations should be applied
|
||||
return false;
|
||||
}
|
||||
|
||||
$uow = $this->em->getUnitOfWork();
|
||||
|
||||
// shortcut for new entities
|
||||
@@ -237,11 +244,11 @@ class OneToManyPersister extends AbstractCollectionPersister
|
||||
return false;
|
||||
}
|
||||
|
||||
$mapping = $coll->getMapping();
|
||||
$class = $this->em->getClassMetadata($mapping['targetEntity']);
|
||||
$sql = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform)
|
||||
. ' WHERE ' . implode('= ? AND ', $class->getIdentifierColumnNames()) . ' = ?';
|
||||
$this
|
||||
->uow
|
||||
->getEntityPersister($mapping['targetEntity'])
|
||||
->delete($element);
|
||||
|
||||
return (bool) $this->conn->executeUpdate($sql, $this->getDeleteRowSQLParameters($coll, $element));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,11 @@ class QueryExpressionVisitor extends ExpressionVisitor
|
||||
Comparison::LTE => Expr\Comparison::LTE
|
||||
);
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $rootAlias;
|
||||
|
||||
/**
|
||||
* @var Expr
|
||||
*/
|
||||
@@ -58,10 +63,13 @@ class QueryExpressionVisitor extends ExpressionVisitor
|
||||
private $parameters = array();
|
||||
|
||||
/**
|
||||
* Constructor with internal initialization.
|
||||
* Constructor
|
||||
*
|
||||
* @param string $rootAlias
|
||||
*/
|
||||
public function __construct()
|
||||
public function __construct($rootAlias)
|
||||
{
|
||||
$this->rootAlias = $rootAlias;
|
||||
$this->expr = new Expr();
|
||||
}
|
||||
|
||||
@@ -133,33 +141,33 @@ class QueryExpressionVisitor extends ExpressionVisitor
|
||||
switch ($comparison->getOperator()) {
|
||||
case Comparison::IN:
|
||||
$this->parameters[] = $parameter;
|
||||
return $this->expr->in($comparison->getField(), $placeholder);
|
||||
return $this->expr->in($this->rootAlias . '.' . $comparison->getField(), $placeholder);
|
||||
|
||||
case Comparison::NIN:
|
||||
$this->parameters[] = $parameter;
|
||||
return $this->expr->notIn($comparison->getField(), $placeholder);
|
||||
return $this->expr->notIn($this->rootAlias . '.' . $comparison->getField(), $placeholder);
|
||||
|
||||
case Comparison::EQ:
|
||||
case Comparison::IS:
|
||||
if ($this->walkValue($comparison->getValue()) === null) {
|
||||
return $this->expr->isNull($comparison->getField());
|
||||
return $this->expr->isNull($this->rootAlias . '.' . $comparison->getField());
|
||||
}
|
||||
$this->parameters[] = $parameter;
|
||||
return $this->expr->eq($comparison->getField(), $placeholder);
|
||||
return $this->expr->eq($this->rootAlias . '.' . $comparison->getField(), $placeholder);
|
||||
|
||||
case Comparison::NEQ:
|
||||
if ($this->walkValue($comparison->getValue()) === null) {
|
||||
return $this->expr->isNotNull($comparison->getField());
|
||||
return $this->expr->isNotNull($this->rootAlias . '.' . $comparison->getField());
|
||||
}
|
||||
$this->parameters[] = $parameter;
|
||||
return $this->expr->neq($comparison->getField(), $placeholder);
|
||||
return $this->expr->neq($this->rootAlias . '.' . $comparison->getField(), $placeholder);
|
||||
|
||||
default:
|
||||
$operator = self::convertComparisonOperator($comparison->getOperator());
|
||||
if ($operator) {
|
||||
$this->parameters[] = $parameter;
|
||||
return new Expr\Comparison(
|
||||
$comparison->getField(),
|
||||
$this->rootAlias . '.' . $comparison->getField(),
|
||||
$operator,
|
||||
$placeholder
|
||||
);
|
||||
|
||||
@@ -456,7 +456,7 @@ class SqlWalker implements TreeWalker
|
||||
}
|
||||
|
||||
$sqlParts[] = (($this->useSqlTableAliases) ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' : '')
|
||||
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
|
||||
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
|
||||
}
|
||||
|
||||
$sql = implode(' AND ', $sqlParts);
|
||||
@@ -496,7 +496,7 @@ class SqlWalker implements TreeWalker
|
||||
default:
|
||||
//@todo: throw exception?
|
||||
return '';
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
$filterClauses = array();
|
||||
@@ -574,7 +574,7 @@ class SqlWalker implements TreeWalker
|
||||
$this->useSqlTableAliases = false;
|
||||
|
||||
return $this->walkUpdateClause($AST->updateClause)
|
||||
. $this->walkWhereClause($AST->whereClause);
|
||||
. $this->walkWhereClause($AST->whereClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -585,7 +585,7 @@ class SqlWalker implements TreeWalker
|
||||
$this->useSqlTableAliases = false;
|
||||
|
||||
return $this->walkDeleteClause($AST->deleteClause)
|
||||
. $this->walkWhereClause($AST->whereClause);
|
||||
. $this->walkWhereClause($AST->whereClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -700,10 +700,10 @@ class SqlWalker implements TreeWalker
|
||||
}
|
||||
|
||||
$addMetaColumns = ! $this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD) &&
|
||||
$this->query->getHydrationMode() == Query::HYDRATE_OBJECT
|
||||
||
|
||||
$this->query->getHydrationMode() != Query::HYDRATE_OBJECT &&
|
||||
$this->query->getHint(Query::HINT_INCLUDE_META_COLUMNS);
|
||||
$this->query->getHydrationMode() == Query::HYDRATE_OBJECT
|
||||
||
|
||||
$this->query->getHydrationMode() != Query::HYDRATE_OBJECT &&
|
||||
$this->query->getHint(Query::HINT_INCLUDE_META_COLUMNS);
|
||||
|
||||
foreach ($this->selectedClasses as $selectedClass) {
|
||||
$class = $selectedClass['class'];
|
||||
@@ -801,10 +801,7 @@ class SqlWalker implements TreeWalker
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($identificationVarDecls as $identificationVariableDecl) {
|
||||
$sql = $this->platform->appendLockHint(
|
||||
$this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration),
|
||||
$this->query->getHint(Query::HINT_LOCK_MODE)
|
||||
);
|
||||
$sql = $this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration);
|
||||
|
||||
foreach ($identificationVariableDecl->joins as $join) {
|
||||
$sql .= $this->walkJoin($join);
|
||||
@@ -846,8 +843,11 @@ class SqlWalker implements TreeWalker
|
||||
$this->rootAliases[] = $dqlAlias;
|
||||
}
|
||||
|
||||
$sql = $this->quoteStrategy->getTableName($class,$this->platform) . ' '
|
||||
. $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||
$sql = $this->platform->appendLockHint(
|
||||
$this->quoteStrategy->getTableName($class, $this->platform) . ' ' .
|
||||
$this->getSQLTableAlias($class->getTableName(), $dqlAlias),
|
||||
$this->query->getHint(Query::HINT_LOCK_MODE)
|
||||
);
|
||||
|
||||
if ($class->isInheritanceTypeJoined()) {
|
||||
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
|
||||
@@ -892,6 +892,8 @@ class SqlWalker implements TreeWalker
|
||||
}
|
||||
}
|
||||
|
||||
$targetTableJoin = null;
|
||||
|
||||
// This condition is not checking ClassMetadata::MANY_TO_ONE, because by definition it cannot
|
||||
// be the owning side and previously we ensured that $assoc is always the owning side of the associations.
|
||||
// The owning side is necessary at this point because only it contains the JoinColumn information.
|
||||
@@ -899,7 +901,7 @@ class SqlWalker implements TreeWalker
|
||||
case ($assoc['type'] & ClassMetadata::TO_ONE):
|
||||
$conditions = array();
|
||||
|
||||
foreach ($assoc['joinColumns'] as $joinColumn) {
|
||||
foreach ($assoc['joinColumns'] as $joinColumn) {
|
||||
$quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform);
|
||||
$quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform);
|
||||
|
||||
@@ -926,7 +928,10 @@ class SqlWalker implements TreeWalker
|
||||
$conditions[] = $filterExpr;
|
||||
}
|
||||
|
||||
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ' . implode(' AND ', $conditions);
|
||||
$targetTableJoin = array(
|
||||
'table' => $targetTableName . ' ' . $targetTableAlias,
|
||||
'condition' => implode(' AND ', $conditions),
|
||||
);
|
||||
break;
|
||||
|
||||
case ($assoc['type'] == ClassMetadata::MANY_TO_MANY):
|
||||
@@ -978,20 +983,30 @@ class SqlWalker implements TreeWalker
|
||||
$conditions[] = $filterExpr;
|
||||
}
|
||||
|
||||
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ' . implode(' AND ', $conditions);
|
||||
$targetTableJoin = array(
|
||||
'table' => $targetTableName . ' ' . $targetTableAlias,
|
||||
'condition' => implode(' AND ', $conditions),
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle WITH clause
|
||||
if ($condExpr !== null) {
|
||||
// Phase 2 AST optimization: Skip processing of ConditionalExpression
|
||||
// if only one ConditionalTerm is defined
|
||||
$sql .= ' AND (' . $this->walkConditionalExpression($condExpr) . ')';
|
||||
$withCondition = (null === $condExpr) ? '' : ('(' . $this->walkConditionalExpression($condExpr) . ')');
|
||||
|
||||
if ($targetClass->isInheritanceTypeJoined()) {
|
||||
$ctiJoins = $this->_generateClassTableInheritanceJoins($targetClass, $joinedDqlAlias);
|
||||
// If we have WITH condition, we need to build nested joins for target class table and cti joins
|
||||
if ($withCondition) {
|
||||
$sql .= '(' . $targetTableJoin['table'] . $ctiJoins . ') ON ' . $targetTableJoin['condition'];
|
||||
} else {
|
||||
$sql .= $targetTableJoin['table'] . ' ON ' . $targetTableJoin['condition'] . $ctiJoins;
|
||||
}
|
||||
} else {
|
||||
$sql .= $targetTableJoin['table'] . ' ON ' . $targetTableJoin['condition'];
|
||||
}
|
||||
|
||||
// FIXME: these should either be nested or all forced to be left joins (DDC-XXX)
|
||||
if ($targetClass->isInheritanceTypeJoined()) {
|
||||
$sql .= $this->_generateClassTableInheritanceJoins($targetClass, $joinedDqlAlias);
|
||||
if ($withCondition) {
|
||||
$sql .= ' AND ' . $withCondition;
|
||||
}
|
||||
|
||||
// Apply the indexes
|
||||
@@ -1439,10 +1454,7 @@ class SqlWalker implements TreeWalker
|
||||
$sqlParts = array ();
|
||||
|
||||
foreach ($identificationVarDecls as $subselectIdVarDecl) {
|
||||
$sql = $this->platform->appendLockHint(
|
||||
$this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration),
|
||||
$this->query->getHint(Query::HINT_LOCK_MODE)
|
||||
);
|
||||
$sql = $this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration);
|
||||
|
||||
foreach ($subselectIdVarDecl->joins as $join) {
|
||||
$sql .= $this->walkJoin($join);
|
||||
@@ -1460,7 +1472,7 @@ class SqlWalker implements TreeWalker
|
||||
public function walkSimpleSelectClause($simpleSelectClause)
|
||||
{
|
||||
return 'SELECT' . ($simpleSelectClause->isDistinct ? ' DISTINCT' : '')
|
||||
. $this->walkSimpleSelectExpression($simpleSelectClause->simpleSelectExpression);
|
||||
. $this->walkSimpleSelectExpression($simpleSelectClause->simpleSelectExpression);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1497,6 +1509,7 @@ class SqlWalker implements TreeWalker
|
||||
break;
|
||||
}
|
||||
|
||||
$fieldType = 'string';
|
||||
switch (true) {
|
||||
case ($e instanceof AST\PathExpression):
|
||||
$fieldName = $e->field;
|
||||
@@ -1517,10 +1530,6 @@ class SqlWalker implements TreeWalker
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$fieldType = 'string';
|
||||
break;
|
||||
}
|
||||
|
||||
$this->scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||
@@ -1595,7 +1604,7 @@ class SqlWalker implements TreeWalker
|
||||
public function walkAggregateExpression($aggExpression)
|
||||
{
|
||||
return $aggExpression->functionName . '(' . ($aggExpression->isDistinct ? 'DISTINCT ' : '')
|
||||
. $this->walkSimpleArithmeticExpression($aggExpression->pathExpression) . ')';
|
||||
. $this->walkSimpleArithmeticExpression($aggExpression->pathExpression) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1890,7 +1899,7 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
// join to target table
|
||||
$sql .= $this->quoteStrategy->getJoinTableName($owningAssoc, $targetClass, $this->platform) . ' ' . $joinTableAlias
|
||||
. ' INNER JOIN ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' ON ';
|
||||
. ' INNER JOIN ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' ON ';
|
||||
|
||||
// join conditions
|
||||
$joinColumns = $assoc['isOwningSide'] ? $joinTable['inverseJoinColumns'] : $joinTable['joinColumns'];
|
||||
@@ -2070,7 +2079,7 @@ class SqlWalker implements TreeWalker
|
||||
if ($betweenExpr->not) $sql .= ' NOT';
|
||||
|
||||
$sql .= ' BETWEEN ' . $this->walkArithmeticExpression($betweenExpr->leftBetweenExpression)
|
||||
. ' AND ' . $this->walkArithmeticExpression($betweenExpr->rightBetweenExpression);
|
||||
. ' AND ' . $this->walkArithmeticExpression($betweenExpr->rightBetweenExpression);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
@@ -894,8 +894,8 @@ class QueryBuilder
|
||||
*/
|
||||
public function andWhere($where)
|
||||
{
|
||||
$where = $this->getDQLPart('where');
|
||||
$args = func_get_args();
|
||||
$where = $this->getDQLPart('where');
|
||||
|
||||
if ($where instanceof Expr\Andx) {
|
||||
$where->addMultiple($args);
|
||||
@@ -927,8 +927,8 @@ class QueryBuilder
|
||||
*/
|
||||
public function orWhere($where)
|
||||
{
|
||||
$where = $this->getDqlPart('where');
|
||||
$args = func_get_args();
|
||||
$where = $this->getDqlPart('where');
|
||||
|
||||
if ($where instanceof Expr\Orx) {
|
||||
$where->addMultiple($args);
|
||||
@@ -1007,8 +1007,8 @@ class QueryBuilder
|
||||
*/
|
||||
public function andHaving($having)
|
||||
{
|
||||
$having = $this->getDqlPart('having');
|
||||
$args = func_get_args();
|
||||
$having = $this->getDqlPart('having');
|
||||
|
||||
if ($having instanceof Expr\Andx) {
|
||||
$having->addMultiple($args);
|
||||
@@ -1030,8 +1030,8 @@ class QueryBuilder
|
||||
*/
|
||||
public function orHaving($having)
|
||||
{
|
||||
$having = $this->getDqlPart('having');
|
||||
$args = func_get_args();
|
||||
$having = $this->getDqlPart('having');
|
||||
|
||||
if ($having instanceof Expr\Orx) {
|
||||
$having->addMultiple($args);
|
||||
@@ -1087,7 +1087,8 @@ class QueryBuilder
|
||||
*/
|
||||
public function addCriteria(Criteria $criteria)
|
||||
{
|
||||
$visitor = new QueryExpressionVisitor();
|
||||
$rootAlias = $this->getRootAlias();
|
||||
$visitor = new QueryExpressionVisitor($rootAlias);
|
||||
|
||||
if ($whereExpression = $criteria->getWhereExpression()) {
|
||||
$this->andWhere($visitor->dispatch($whereExpression));
|
||||
@@ -1098,7 +1099,7 @@ class QueryBuilder
|
||||
|
||||
if ($criteria->getOrderings()) {
|
||||
foreach ($criteria->getOrderings() as $sort => $order) {
|
||||
$this->addOrderBy($sort, $order);
|
||||
$this->addOrderBy($rootAlias . '.' . $sort, $order);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ EOT
|
||||
|
||||
// Process destination directory
|
||||
if ( ! is_dir($destPath = $input->getArgument('dest-path'))) {
|
||||
mkdir($destPath, 0777, true);
|
||||
mkdir($destPath, 0775, true);
|
||||
}
|
||||
$destPath = realpath($destPath);
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ EOT
|
||||
}
|
||||
|
||||
if ( ! is_dir($destPath)) {
|
||||
mkdir($destPath, 0777, true);
|
||||
mkdir($destPath, 0775, true);
|
||||
}
|
||||
|
||||
$destPath = realpath($destPath);
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Doctrine\ORM\Tools\Console;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Doctrine\ORM\Version;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
|
||||
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
|
||||
@@ -35,10 +35,10 @@ class ConsoleRunner
|
||||
/**
|
||||
* Create a Symfony Console HelperSet
|
||||
*
|
||||
* @param EntityManager $entityManager
|
||||
* @param EntityManagerInterface $entityManager
|
||||
* @return HelperSet
|
||||
*/
|
||||
public static function createHelperSet(EntityManager $entityManager)
|
||||
public static function createHelperSet(EntityManagerInterface $entityManager)
|
||||
{
|
||||
return new HelperSet(array(
|
||||
'db' => new ConnectionHelper($entityManager->getConnection()),
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
|
||||
namespace Doctrine\ORM\Tools\Console\Helper;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Helper\Helper;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
|
||||
/**
|
||||
* Doctrine CLI Connection Helper.
|
||||
@@ -35,18 +36,18 @@ use Doctrine\ORM\EntityManager;
|
||||
class EntityManagerHelper extends Helper
|
||||
{
|
||||
/**
|
||||
* Doctrine ORM EntityManager.
|
||||
* Doctrine ORM EntityManagerInterface.
|
||||
*
|
||||
* @var EntityManager
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
* @param EntityManagerInterface $em
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->_em = $em;
|
||||
}
|
||||
@@ -54,7 +55,7 @@ class EntityManagerHelper extends Helper
|
||||
/**
|
||||
* Retrieves Doctrine ORM EntityManager.
|
||||
*
|
||||
* @return EntityManager
|
||||
* @return EntityManagerInterface
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
|
||||
@@ -340,7 +340,7 @@ public function __construct()
|
||||
$dir = dirname($path);
|
||||
|
||||
if ( ! is_dir($dir)) {
|
||||
mkdir($dir, 0777, true);
|
||||
mkdir($dir, 0775, true);
|
||||
}
|
||||
|
||||
$this->isNew = !file_exists($path) || (file_exists($path) && $this->regenerateEntityIfExists);
|
||||
@@ -365,6 +365,7 @@ public function __construct()
|
||||
} elseif ( ! $this->isNew && $this->updateEntityIfExists) {
|
||||
file_put_contents($path, $this->generateUpdatedEntityClass($metadata, $path));
|
||||
}
|
||||
chmod($path, 0664);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -679,7 +680,7 @@ public function __construct()
|
||||
if ($token[0] == T_NAMESPACE) {
|
||||
$lastSeenNamespace = "";
|
||||
$inNamespace = true;
|
||||
} elseif ($token[0] == T_CLASS) {
|
||||
} elseif ($token[0] == T_CLASS && $tokens[$i-1][0] != T_DOUBLE_COLON) {
|
||||
$inClass = true;
|
||||
} elseif ($token[0] == T_FUNCTION) {
|
||||
if ($tokens[$i+2][0] == T_STRING) {
|
||||
@@ -701,9 +702,9 @@ public function __construct()
|
||||
*/
|
||||
protected function hasProperty($property, ClassMetadataInfo $metadata)
|
||||
{
|
||||
if ($this->extendsClass()) {
|
||||
if ($this->extendsClass() || (!$this->isNew && 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;
|
||||
}
|
||||
@@ -723,9 +724,9 @@ public function __construct()
|
||||
*/
|
||||
protected function hasMethod($method, ClassMetadataInfo $metadata)
|
||||
{
|
||||
if ($this->extendsClass()) {
|
||||
if ($this->extendsClass() || (!$this->isNew && 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;
|
||||
@@ -1074,7 +1075,7 @@ public function __construct()
|
||||
|
||||
$lines[] = $this->generateFieldMappingPropertyDocBlock($fieldMapping, $metadata);
|
||||
$lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldMapping['fieldName']
|
||||
. (isset($fieldMapping['default']) ? ' = ' . var_export($fieldMapping['default'], true) : null) . ";\n";
|
||||
. (isset($fieldMapping['options']['default']) ? ' = ' . var_export($fieldMapping['options']['default'], true) : null) . ";\n";
|
||||
}
|
||||
|
||||
return implode("\n", $lines);
|
||||
|
||||
@@ -96,11 +96,12 @@ class <className> extends EntityRepository
|
||||
$dir = dirname($path);
|
||||
|
||||
if ( ! is_dir($dir)) {
|
||||
mkdir($dir, 0777, true);
|
||||
mkdir($dir, 0775, true);
|
||||
}
|
||||
|
||||
if ( ! file_exists($path)) {
|
||||
file_put_contents($path, $code);
|
||||
chmod($path, 0664);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ abstract class AbstractExporter
|
||||
public function export()
|
||||
{
|
||||
if ( ! is_dir($this->_outputDir)) {
|
||||
mkdir($this->_outputDir, 0777, true);
|
||||
mkdir($this->_outputDir, 0775, true);
|
||||
}
|
||||
|
||||
foreach ($this->_metadata as $metadata) {
|
||||
@@ -139,12 +139,13 @@ abstract class AbstractExporter
|
||||
$path = $this->_generateOutputPath($metadata);
|
||||
$dir = dirname($path);
|
||||
if ( ! is_dir($dir)) {
|
||||
mkdir($dir, 0777, true);
|
||||
mkdir($dir, 0775, true);
|
||||
}
|
||||
if (file_exists($path) && !$this->_overwriteExistingFiles) {
|
||||
throw ExportException::attemptOverwriteExistingFile($path);
|
||||
}
|
||||
file_put_contents($path, $output);
|
||||
chmod($path, 0664);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ class XmlExporter extends AbstractExporter
|
||||
}
|
||||
|
||||
if (isset($field['unique']) && $field['unique']) {
|
||||
$fieldXml->addAttribute('unique', $field['unique']);
|
||||
$fieldXml->addAttribute('unique', $field['unique'] ? 'true' : 'false');
|
||||
}
|
||||
|
||||
if (isset($field['options'])) {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
namespace Doctrine\ORM\Tools\Pagination;
|
||||
|
||||
use Doctrine\ORM\Query\AST\PathExpression;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
use Doctrine\ORM\Query\AST\SelectStatement;
|
||||
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
|
||||
@@ -92,25 +93,22 @@ class LimitSubqueryOutputWalker extends SqlWalker
|
||||
*/
|
||||
public function walkSelectStatement(SelectStatement $AST)
|
||||
{
|
||||
if ($this->platform instanceof PostgreSqlPlatform) {
|
||||
// Set every select expression as visible(hidden = false) to
|
||||
// make $AST to have scalar mappings properly
|
||||
$hiddens = array();
|
||||
foreach ($AST->selectClause->selectExpressions as $idx => $expr) {
|
||||
$hiddens[$idx] = $expr->hiddenAliasResultVariable;
|
||||
$expr->hiddenAliasResultVariable = false;
|
||||
}
|
||||
|
||||
$innerSql = parent::walkSelectStatement($AST);
|
||||
|
||||
// Restore hiddens
|
||||
foreach ($AST->selectClause->selectExpressions as $idx => $expr) {
|
||||
$expr->hiddenAliasResultVariable = $hiddens[$idx];
|
||||
}
|
||||
} else {
|
||||
$innerSql = parent::walkSelectStatement($AST);
|
||||
// Set every select expression as visible(hidden = false) to
|
||||
// make $AST have scalar mappings properly - this is relevant for referencing selected
|
||||
// fields from outside the subquery, for example in the ORDER BY segment
|
||||
$hiddens = array();
|
||||
|
||||
foreach ($AST->selectClause->selectExpressions as $idx => $expr) {
|
||||
$hiddens[$idx] = $expr->hiddenAliasResultVariable;
|
||||
$expr->hiddenAliasResultVariable = false;
|
||||
}
|
||||
|
||||
$innerSql = parent::walkSelectStatement($AST);
|
||||
|
||||
// Restore hiddens
|
||||
foreach ($AST->selectClause->selectExpressions as $idx => $expr) {
|
||||
$expr->hiddenAliasResultVariable = $hiddens[$idx];
|
||||
}
|
||||
|
||||
// Find out the SQL alias of the identifier column of the root entity.
|
||||
// It may be possible to make this work with multiple root entities but that
|
||||
@@ -160,11 +158,8 @@ class LimitSubqueryOutputWalker extends SqlWalker
|
||||
$sql = sprintf('SELECT DISTINCT %s FROM (%s) dctrn_result',
|
||||
implode(', ', $sqlIdentifier), $innerSql);
|
||||
|
||||
if ($this->platform instanceof PostgreSqlPlatform ||
|
||||
$this->platform instanceof OraclePlatform) {
|
||||
//http://www.doctrine-project.org/jira/browse/DDC-1958
|
||||
$this->preserveSqlOrdering($AST, $sqlIdentifier, $innerSql, $sql);
|
||||
}
|
||||
// http://www.doctrine-project.org/jira/browse/DDC-1958
|
||||
$sql = $this->preserveSqlOrdering($AST, $sqlIdentifier, $innerSql, $sql);
|
||||
|
||||
// Apply the limit and offset.
|
||||
$sql = $this->platform->modifyLimitQuery(
|
||||
@@ -181,7 +176,7 @@ class LimitSubqueryOutputWalker extends SqlWalker
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates new SQL for Postgresql or Oracle if necessary.
|
||||
*
|
||||
@@ -192,19 +187,21 @@ class LimitSubqueryOutputWalker extends SqlWalker
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function preserveSqlOrdering(SelectStatement $AST, array $sqlIdentifier, $innerSql, &$sql)
|
||||
public function preserveSqlOrdering(SelectStatement $AST, array $sqlIdentifier, $innerSql, $sql)
|
||||
{
|
||||
// For every order by, find out the SQL alias by inspecting the ResultSetMapping.
|
||||
$sqlOrderColumns = array();
|
||||
$orderBy = array();
|
||||
if (isset($AST->orderByClause)) {
|
||||
foreach ($AST->orderByClause->orderByItems as $item) {
|
||||
$possibleAliases = (is_object($item->expression))
|
||||
? array_keys($this->rsm->fieldMappings, $item->expression->field)
|
||||
: array_keys($this->rsm->scalarMappings, $item->expression);
|
||||
$expression = $item->expression;
|
||||
|
||||
$possibleAliases = $expression instanceof PathExpression
|
||||
? array_keys($this->rsm->fieldMappings, $expression->field)
|
||||
: array_keys($this->rsm->scalarMappings, $expression);
|
||||
|
||||
foreach ($possibleAliases as $alias) {
|
||||
if (!is_object($item->expression) || $this->rsm->columnOwnerMap[$alias] == $item->expression->identificationVariable) {
|
||||
if (!is_object($expression) || $this->rsm->columnOwnerMap[$alias] == $expression->identificationVariable) {
|
||||
$sqlOrderColumns[] = $alias;
|
||||
$orderBy[] = $alias . ' ' . $item->type;
|
||||
break;
|
||||
@@ -215,11 +212,6 @@ class LimitSubqueryOutputWalker extends SqlWalker
|
||||
$sqlOrderColumns = array_diff($sqlOrderColumns, $sqlIdentifier);
|
||||
}
|
||||
|
||||
// We don't need orderBy in inner query.
|
||||
// However at least on 5.4.6 I'm getting a segmentation fault and thus we don't clear it for now.
|
||||
/*$AST->orderByClause = null;
|
||||
$innerSql = parent::walkSelectStatement($AST);*/
|
||||
|
||||
if (count($orderBy)) {
|
||||
$sql = sprintf(
|
||||
'SELECT DISTINCT %s FROM (%s) dctrn_result ORDER BY %s',
|
||||
@@ -228,5 +220,7 @@ class LimitSubqueryOutputWalker extends SqlWalker
|
||||
implode(', ', $orderBy)
|
||||
);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
namespace Doctrine\ORM\Tools\Pagination;
|
||||
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
@@ -118,31 +119,8 @@ class Paginator implements \Countable, \IteratorAggregate
|
||||
public function count()
|
||||
{
|
||||
if ($this->count === null) {
|
||||
/* @var $countQuery Query */
|
||||
$countQuery = $this->cloneQuery($this->query);
|
||||
|
||||
if ( ! $countQuery->hasHint(CountWalker::HINT_DISTINCT)) {
|
||||
$countQuery->setHint(CountWalker::HINT_DISTINCT, true);
|
||||
}
|
||||
|
||||
if ($this->useOutputWalker($countQuery)) {
|
||||
$platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win
|
||||
|
||||
$rsm = new ResultSetMapping();
|
||||
$rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count');
|
||||
|
||||
$countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
|
||||
$countQuery->setResultSetMapping($rsm);
|
||||
} else {
|
||||
$this->appendTreeWalker($countQuery, 'Doctrine\ORM\Tools\Pagination\CountWalker');
|
||||
}
|
||||
|
||||
$countQuery->setFirstResult(null)->setMaxResults(null);
|
||||
|
||||
try {
|
||||
$data = $countQuery->getScalarResult();
|
||||
$data = array_map('current', $data);
|
||||
$this->count = array_sum($data);
|
||||
$this->count = array_sum(array_map('current', $this->getCountQuery()->getScalarResult()));
|
||||
} catch(NoResultException $e) {
|
||||
$this->count = 0;
|
||||
}
|
||||
@@ -249,4 +227,50 @@ class Paginator implements \Countable, \IteratorAggregate
|
||||
$hints[] = $walkerClass;
|
||||
$query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $hints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Query prepared to count.
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
private function getCountQuery()
|
||||
{
|
||||
/* @var $countQuery Query */
|
||||
$countQuery = $this->cloneQuery($this->query);
|
||||
|
||||
if ( ! $countQuery->hasHint(CountWalker::HINT_DISTINCT)) {
|
||||
$countQuery->setHint(CountWalker::HINT_DISTINCT, true);
|
||||
}
|
||||
|
||||
if ($this->useOutputWalker($countQuery)) {
|
||||
$platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win
|
||||
|
||||
$rsm = new ResultSetMapping();
|
||||
$rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count');
|
||||
|
||||
$countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
|
||||
$countQuery->setResultSetMapping($rsm);
|
||||
} else {
|
||||
$this->appendTreeWalker($countQuery, 'Doctrine\ORM\Tools\Pagination\CountWalker');
|
||||
}
|
||||
|
||||
$countQuery->setFirstResult(null)->setMaxResults(null);
|
||||
|
||||
$parser = new Parser($countQuery);
|
||||
$parameterMappings = $parser->parse()->getParameterMappings();
|
||||
/* @var $parameters \Doctrine\Common\Collections\Collection|\Doctrine\ORM\Query\Parameter[] */
|
||||
$parameters = $countQuery->getParameters();
|
||||
|
||||
foreach ($parameters as $key => $parameter) {
|
||||
$parameterName = $parameter->getName();
|
||||
|
||||
if( ! (isset($parameterMappings[$parameterName]) || array_key_exists($parameterName, $parameterMappings))) {
|
||||
unset($parameters[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$countQuery->setParameters($parameters);
|
||||
|
||||
return $countQuery;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector;
|
||||
use Doctrine\DBAL\Schema\Visitor\RemoveNamespacedAssets;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Internal\CommitOrderCalculator;
|
||||
use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs;
|
||||
@@ -47,7 +47,7 @@ use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
|
||||
class SchemaTool
|
||||
{
|
||||
/**
|
||||
* @var \Doctrine\ORM\EntityManager
|
||||
* @var \Doctrine\ORM\EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
@@ -67,9 +67,9 @@ class SchemaTool
|
||||
* Initializes a new SchemaTool instance that uses the connection of the
|
||||
* provided EntityManager.
|
||||
*
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
* @param \Doctrine\ORM\EntityManagerInterface $em
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->platform = $em->getConnection()->getDatabasePlatform();
|
||||
@@ -430,7 +430,7 @@ class SchemaTool
|
||||
$knownOptions = array('comment', 'unsigned', 'fixed', 'default');
|
||||
|
||||
foreach ($knownOptions as $knownOption) {
|
||||
if ( isset($mapping['options'][$knownOption])) {
|
||||
if (array_key_exists($knownOption, $mapping['options'])) {
|
||||
$options[$knownOption] = $mapping['options'][$knownOption];
|
||||
|
||||
unset($mapping['options'][$knownOption]);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
namespace Doctrine\ORM\Tools;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
@@ -37,14 +37,14 @@ use Doctrine\DBAL\Types\Type;
|
||||
class SchemaValidator
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* @param EntityManager $em
|
||||
* @param EntityManagerInterface $em
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
@@ -530,7 +530,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
}
|
||||
|
||||
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preFlush);
|
||||
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preFlush) & ~ListenersInvoker::INVOKE_MANAGER;
|
||||
|
||||
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
|
||||
$this->listenersInvoker->invoke($class, Events::preFlush, $entity, new PreFlushEventArgs($this->em), $invoke);
|
||||
@@ -541,7 +541,15 @@ class UnitOfWork implements PropertyChangedListener
|
||||
foreach ($class->reflFields as $name => $refProp) {
|
||||
$value = $refProp->getValue($entity);
|
||||
|
||||
if ($class->isCollectionValuedAssociation($name) && $value !== null && ! ($value instanceof PersistentCollection)) {
|
||||
if ($class->isCollectionValuedAssociation($name) && $value !== null) {
|
||||
if ($value instanceof PersistentCollection) {
|
||||
if ($value->getOwner() === $entity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = new ArrayCollection($value->getValues());
|
||||
}
|
||||
|
||||
// If $value is not a Collection then use an ArrayCollection.
|
||||
if ( ! $value instanceof Collection) {
|
||||
$value = new ArrayCollection($value);
|
||||
@@ -894,20 +902,24 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$actualData = array();
|
||||
|
||||
foreach ($class->reflFields as $name => $refProp) {
|
||||
if ( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) {
|
||||
if (( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity())
|
||||
&& ($name !== $class->versionField)
|
||||
&& ! $class->isCollectionValuedAssociation($name)) {
|
||||
$actualData[$name] = $refProp->getValue($entity);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset($this->originalEntityData[$oid])) {
|
||||
throw new \RuntimeException('Cannot call recomputeSingleEntityChangeSet before computeChangeSet on an entity.');
|
||||
}
|
||||
|
||||
$originalData = $this->originalEntityData[$oid];
|
||||
$changeSet = array();
|
||||
|
||||
foreach ($actualData as $propName => $actualValue) {
|
||||
$orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
|
||||
|
||||
if (is_object($orgValue) && $orgValue !== $actualValue) {
|
||||
$changeSet[$propName] = array($orgValue, $actualValue);
|
||||
} else if ($orgValue != $actualValue || ($orgValue === null ^ $actualValue === null)) {
|
||||
if ($orgValue !== $actualValue) {
|
||||
$changeSet[$propName] = array($orgValue, $actualValue);
|
||||
}
|
||||
}
|
||||
@@ -915,8 +927,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ($changeSet) {
|
||||
if (isset($this->entityChangeSets[$oid])) {
|
||||
$this->entityChangeSets[$oid] = array_merge($this->entityChangeSets[$oid], $changeSet);
|
||||
} else if ( ! isset($this->entityInsertions[$oid])) {
|
||||
$this->entityChangeSets[$oid] = $changeSet;
|
||||
$this->entityUpdates[$oid] = $entity;
|
||||
}
|
||||
|
||||
$this->originalEntityData[$oid] = $actualData;
|
||||
}
|
||||
}
|
||||
@@ -1616,6 +1630,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
case self::STATE_REMOVED:
|
||||
// Entity becomes managed again
|
||||
unset($this->entityDeletions[$oid]);
|
||||
$this->addToIdentityMap($entity);
|
||||
|
||||
$this->entityStates[$oid] = self::STATE_MANAGED;
|
||||
break;
|
||||
@@ -1736,6 +1751,8 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$associatedId = $this->getEntityIdentifier($idValue);
|
||||
|
||||
$flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]];
|
||||
} else {
|
||||
$flatId[$idField] = $idValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2231,6 +2248,8 @@ class UnitOfWork implements PropertyChangedListener
|
||||
function ($assoc) { return $assoc['isCascadeRemove']; }
|
||||
);
|
||||
|
||||
$entitiesToCascade = array();
|
||||
|
||||
foreach ($associationMappings as $assoc) {
|
||||
if ($entity instanceof Proxy && !$entity->__isInitialized__) {
|
||||
$entity->__load();
|
||||
@@ -2243,18 +2262,22 @@ class UnitOfWork implements PropertyChangedListener
|
||||
case (is_array($relatedEntities)):
|
||||
// If its a PersistentCollection initialization is intended! No unwrap!
|
||||
foreach ($relatedEntities as $relatedEntity) {
|
||||
$this->doRemove($relatedEntity, $visited);
|
||||
$entitiesToCascade[] = $relatedEntity;
|
||||
}
|
||||
break;
|
||||
|
||||
case ($relatedEntities !== null):
|
||||
$this->doRemove($relatedEntities, $visited);
|
||||
$entitiesToCascade[] = $relatedEntities;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($entitiesToCascade as $relatedEntity) {
|
||||
$this->doRemove($relatedEntity, $visited);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2292,6 +2315,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
return;
|
||||
}
|
||||
|
||||
if ($entity instanceof Proxy && !$entity->__isInitialized__) {
|
||||
$entity->__load();
|
||||
}
|
||||
|
||||
$entityVersion = $class->reflFields[$class->versionField]->getValue($entity);
|
||||
|
||||
if ($entityVersion != $lockVersion) {
|
||||
@@ -2471,16 +2498,16 @@ class UnitOfWork implements PropertyChangedListener
|
||||
? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']]
|
||||
: $data[$fieldName];
|
||||
}
|
||||
|
||||
$idHash = implode(' ', $id);
|
||||
} else {
|
||||
$idHash = isset($class->associationMappings[$class->identifier[0]])
|
||||
$id = isset($class->associationMappings[$class->identifier[0]])
|
||||
? $data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']]
|
||||
: $data[$class->identifier[0]];
|
||||
|
||||
$id = array($class->identifier[0] => $idHash);
|
||||
$id = array($class->identifier[0] => $id);
|
||||
}
|
||||
|
||||
$idHash = implode(' ', $id);
|
||||
|
||||
if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
|
||||
$entity = $this->identityMap[$class->rootEntityName][$idHash];
|
||||
$oid = spl_object_hash($entity);
|
||||
@@ -2490,14 +2517,14 @@ class UnitOfWork implements PropertyChangedListener
|
||||
&& isset($hints[Query::HINT_REFRESH_ENTITY])
|
||||
&& ($unmanagedProxy = $hints[Query::HINT_REFRESH_ENTITY]) !== $entity
|
||||
&& $unmanagedProxy instanceof Proxy
|
||||
&& (($unmanagedProxyClass = $this->em->getClassMetadata(get_class($unmanagedProxy))) === $class)
|
||||
&& $this->isIdentifierEquals($unmanagedProxy, $entity)
|
||||
) {
|
||||
// DDC-1238 - we have a managed instance, but it isn't the provided one.
|
||||
// Therefore we clear its identifier. Also, we must re-fetch metadata since the
|
||||
// refreshed object may be anything
|
||||
|
||||
foreach ($unmanagedProxyClass->identifier as $fieldName) {
|
||||
$unmanagedProxyClass->reflFields[$fieldName]->setValue($unmanagedProxy, null);
|
||||
foreach ($class->identifier as $fieldName) {
|
||||
$class->reflFields[$fieldName]->setValue($unmanagedProxy, null);
|
||||
}
|
||||
|
||||
return $unmanagedProxy;
|
||||
@@ -3206,4 +3233,37 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$this->evm->dispatchEvent(Events::postFlush, new PostFlushEventArgs($this->em));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if two given entities actually are the same based on identifier comparison
|
||||
*
|
||||
* @param object $entity1
|
||||
* @param object $entity2
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isIdentifierEquals($entity1, $entity2)
|
||||
{
|
||||
if ($entity1 === $entity2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$class = $this->em->getClassMetadata(get_class($entity1));
|
||||
|
||||
if ($class !== $this->em->getClassMetadata(get_class($entity2))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$oid1 = spl_object_hash($entity1);
|
||||
$oid2 = spl_object_hash($entity2);
|
||||
|
||||
$id1 = isset($this->entityIdentifiers[$oid1])
|
||||
? $this->entityIdentifiers[$oid1]
|
||||
: $this->flattenIdentifier($class, $class->getIdentifierValues($entity1));
|
||||
$id2 = isset($this->entityIdentifiers[$oid2])
|
||||
? $this->entityIdentifiers[$oid2]
|
||||
: $this->flattenIdentifier($class, $class->getIdentifierValues($entity2));
|
||||
|
||||
return $id1 === $id2 || implode(' ', $id1) === implode(' ', $id2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class Version
|
||||
/**
|
||||
* Current Doctrine Version
|
||||
*/
|
||||
const VERSION = '2.4.1';
|
||||
const VERSION = '2.4.8';
|
||||
|
||||
/**
|
||||
* Compares a Doctrine version with the current one.
|
||||
|
||||
@@ -83,7 +83,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fetchColumn($statement, array $params = array(), $colnum = 0)
|
||||
public function fetchColumn($statement, array $params = array(), $column = 0, array $types = array())
|
||||
{
|
||||
return $this->_fetchOneResult;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\DDC1590;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @MappedSuperClass
|
||||
*/
|
||||
abstract class DDC1590Entity
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @Column(type="datetime")
|
||||
*/
|
||||
protected $created_at;
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\DDC1590;
|
||||
|
||||
use Doctrine\Tests\Models\DDC1590\DDC1590Entity;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="users")
|
||||
*/
|
||||
class DDC1590User extends DDC1590Entity
|
||||
{
|
||||
/**
|
||||
* @Column(type="string", length=255)
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
}
|
||||
@@ -137,6 +137,11 @@ class ECommerceProduct
|
||||
}
|
||||
}
|
||||
|
||||
public function setCategories($categories)
|
||||
{
|
||||
$this->categories = $categories;
|
||||
}
|
||||
|
||||
public function getCategories()
|
||||
{
|
||||
return $this->categories;
|
||||
@@ -166,6 +171,9 @@ class ECommerceProduct
|
||||
public function __clone()
|
||||
{
|
||||
$this->isCloned = true;
|
||||
if ($this->categories) {
|
||||
$this->categories = clone $this->categories;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\NullDefault;
|
||||
|
||||
/** @Entity */
|
||||
class NullDefaultColumn
|
||||
{
|
||||
/** @Id @GeneratedValue @Column(type="integer") */
|
||||
public $id;
|
||||
|
||||
/** @Column(options={"default":NULL}) */
|
||||
public $nullDefault;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\Tweet;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="tweet_tweet")
|
||||
*/
|
||||
class Tweet
|
||||
{
|
||||
const CLASSNAME = __CLASS__;
|
||||
|
||||
/**
|
||||
* @Id
|
||||
* @GeneratedValue
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @Column(type="string", length=140)
|
||||
*/
|
||||
public $content = '';
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="User", inversedBy="tweets", cascade={"persist"}, fetch="EXTRA_LAZY")
|
||||
*/
|
||||
public $author;
|
||||
|
||||
/**
|
||||
* @param User $author
|
||||
*/
|
||||
public function setAuthor(User $author)
|
||||
{
|
||||
$this->author = $author;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\Tweet;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="tweet_user")
|
||||
*/
|
||||
class User
|
||||
{
|
||||
const CLASSNAME = __CLASS__;
|
||||
|
||||
/**
|
||||
* @Id
|
||||
* @GeneratedValue
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @Column(type="string")
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="Tweet", mappedBy="author", cascade={"persist"}, fetch="EXTRA_LAZY")
|
||||
*/
|
||||
public $tweets;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="UserList", mappedBy="owner", fetch="EXTRA_LAZY", orphanRemoval=true)
|
||||
*/
|
||||
public $userLists;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->tweets = new ArrayCollection();
|
||||
$this->userLists = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function addTweet(Tweet $tweet)
|
||||
{
|
||||
$tweet->setAuthor($this);
|
||||
$this->tweets->add($tweet);
|
||||
}
|
||||
|
||||
public function addUserList(UserList $userList)
|
||||
{
|
||||
$userList->owner = $this;
|
||||
$this->userLists->add($userList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\Tweet;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="tweet_user_list")
|
||||
*/
|
||||
class UserList
|
||||
{
|
||||
const CLASSNAME = __CLASS__;
|
||||
|
||||
/**
|
||||
* @Id
|
||||
* @GeneratedValue
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @Column(type="string")
|
||||
*/
|
||||
public $listName;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="User", inversedBy="userLists")
|
||||
*/
|
||||
public $owner;
|
||||
}
|
||||
@@ -3,6 +3,9 @@
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
use Doctrine\Tests\Models\Tweet\Tweet;
|
||||
use Doctrine\Tests\Models\Tweet\User;
|
||||
use Doctrine\Tests\Models\Tweet\UserList;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
@@ -22,7 +25,10 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->useModelSet('tweet');
|
||||
$this->useModelSet('cms');
|
||||
$this->useModelSet('tweet');
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
@@ -363,7 +369,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$user->articles->removeElement($article);
|
||||
|
||||
$this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
|
||||
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
|
||||
$this->assertEquals($queryCount, $this->getCurrentQueryCount());
|
||||
|
||||
// Test One to Many removal with Entity state as new
|
||||
$article = new \Doctrine\Tests\Models\CMS\CmsArticle();
|
||||
@@ -384,7 +390,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$user->articles->removeElement($article);
|
||||
|
||||
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Removing a persisted entity should cause one query to be executed.");
|
||||
$this->assertEquals($queryCount, $this->getCurrentQueryCount(), "Removing a persisted entity should cause one query to be executed.");
|
||||
$this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
|
||||
|
||||
// Test One to Many removal with Entity state as managed
|
||||
@@ -650,4 +656,204 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->topic = $article1->topic;
|
||||
$this->phonenumber = $phonenumber1->phonenumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3343
|
||||
*/
|
||||
public function testRemoveManagedElementFromOneToManyExtraLazyCollectionIsNoOp()
|
||||
{
|
||||
list($userId, $tweetId) = $this->loadTweetFixture();
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
|
||||
$user->tweets->removeElement($this->_em->find(Tweet::CLASSNAME, $tweetId));
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
|
||||
$this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3343
|
||||
*/
|
||||
public function testRemoveManagedElementFromOneToManyExtraLazyCollectionWithoutDeletingTheTargetEntityEntryIsNoOp()
|
||||
{
|
||||
list($userId, $tweetId) = $this->loadTweetFixture();
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
$tweet = $this->_em->find(Tweet::CLASSNAME, $tweetId);
|
||||
|
||||
$user->tweets->removeElement($tweet);
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
/* @var $tweet Tweet */
|
||||
$tweet = $this->_em->find(Tweet::CLASSNAME, $tweetId);
|
||||
$this->assertInstanceOf(
|
||||
Tweet::CLASSNAME,
|
||||
$tweet,
|
||||
'Even though the collection is extra lazy, the tweet should not have been deleted'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
User::CLASSNAME,
|
||||
$tweet->author,
|
||||
'Tweet author link has not been removed - need to update the owning side first'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3343
|
||||
*/
|
||||
public function testRemovingManagedLazyProxyFromExtraLazyOneToManyDoesRemoveTheAssociationButNotTheEntity()
|
||||
{
|
||||
list($userId, $tweetId) = $this->loadTweetFixture();
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
$tweet = $this->_em->getReference(Tweet::CLASSNAME, $tweetId);
|
||||
|
||||
$user->tweets->removeElement($this->_em->getReference(Tweet::CLASSNAME, $tweetId));
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
/* @var $tweet Tweet */
|
||||
$tweet = $this->_em->find(Tweet::CLASSNAME, $tweet->id);
|
||||
$this->assertInstanceOf(
|
||||
Tweet::CLASSNAME,
|
||||
$tweet,
|
||||
'Even though the collection is extra lazy, the tweet should not have been deleted'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(User::CLASSNAME, $tweet->author);
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
|
||||
$this->assertCount(1, $user->tweets, 'Element was not removed - need to update the owning side first');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3343
|
||||
*/
|
||||
public function testRemoveOrphanedManagedElementFromOneToManyExtraLazyCollection()
|
||||
{
|
||||
list($userId, $userListId) = $this->loadUserListFixture();
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
|
||||
$user->userLists->removeElement($this->_em->find(UserList::CLASSNAME, $userListId));
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
|
||||
$this->assertCount(0, $user->userLists, 'Element was removed from association due to orphan removal');
|
||||
$this->assertNull(
|
||||
$this->_em->find(UserList::CLASSNAME, $userListId),
|
||||
'Element was deleted due to orphan removal'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3343
|
||||
*/
|
||||
public function testRemoveOrphanedUnManagedElementFromOneToManyExtraLazyCollection()
|
||||
{
|
||||
list($userId, $userListId) = $this->loadUserListFixture();
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
|
||||
$user->userLists->removeElement(new UserList());
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
/* @var $userList UserList */
|
||||
$userList = $this->_em->find(UserList::CLASSNAME, $userListId);
|
||||
$this->assertInstanceOf(
|
||||
UserList::CLASSNAME,
|
||||
$userList,
|
||||
'Even though the collection is extra lazy + orphan removal, the user list should not have been deleted'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
User::CLASSNAME,
|
||||
$userList->owner,
|
||||
'User list to owner link has not been removed'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3343
|
||||
*/
|
||||
public function testRemoveOrphanedManagedLazyProxyFromExtraLazyOneToMany()
|
||||
{
|
||||
list($userId, $userListId) = $this->loadUserListFixture();
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
|
||||
$user->userLists->removeElement($this->_em->getReference(UserList::CLASSNAME, $userListId));
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
/* @var $user User */
|
||||
$user = $this->_em->find(User::CLASSNAME, $userId);
|
||||
|
||||
$this->assertCount(0, $user->userLists, 'Element was removed from association due to orphan removal');
|
||||
$this->assertNull(
|
||||
$this->_em->find(UserList::CLASSNAME, $userListId),
|
||||
'Element was deleted due to orphan removal'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[] ordered tuple: user id and tweet id
|
||||
*/
|
||||
private function loadTweetFixture()
|
||||
{
|
||||
$user = new User();
|
||||
$tweet = new Tweet();
|
||||
|
||||
$user->name = 'ocramius';
|
||||
$tweet->content = 'The cat is on the table';
|
||||
|
||||
$user->addTweet($tweet);
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->persist($tweet);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
return array($user->id, $tweet->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[] ordered tuple: user id and user list id
|
||||
*/
|
||||
private function loadUserListFixture()
|
||||
{
|
||||
$user = new User();
|
||||
$userList = new UserList();
|
||||
|
||||
$user->name = 'ocramius';
|
||||
$userList->listName = 'PHP Developers to follow closely';
|
||||
|
||||
$user->addUserList($userList);
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->persist($userList);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
return array($user->id, $userList->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +152,19 @@ class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testLockWorksWithProxy()
|
||||
{
|
||||
$test = new OptimisticStandard();
|
||||
$test->name = 'test';
|
||||
$this->_em->persist($test);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$proxy = $this->_em->getReference('Doctrine\Tests\ORM\Functional\Locking\OptimisticStandard', $test->id);
|
||||
|
||||
$this->_em->lock($proxy, LockMode::OPTIMISTIC, 1);
|
||||
}
|
||||
|
||||
public function testOptimisticTimestampSetsDefaultValue()
|
||||
{
|
||||
$test = new OptimisticTimestamp();
|
||||
|
||||
@@ -11,6 +11,7 @@ use Doctrine\Tests\Models\CMS\CmsGroup;
|
||||
use Doctrine\Tests\Models\CMS\CmsArticle;
|
||||
use Doctrine\Tests\Models\CMS\CmsComment;
|
||||
use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||
use ReflectionMethod;
|
||||
|
||||
/**
|
||||
* @group DDC-1613
|
||||
@@ -150,6 +151,36 @@ class PaginationTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertCount(1, $paginator->getIterator());
|
||||
$this->assertEquals(1, $paginator->count());
|
||||
}
|
||||
|
||||
public function testCountQueryStripsParametersInSelect()
|
||||
{
|
||||
$query = $this->_em->createQuery(
|
||||
'SELECT u, (CASE WHEN u.id < :vipMaxId THEN 1 ELSE 0 END) AS hidden promotedFirst
|
||||
FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u
|
||||
WHERE u.id < :id or 1=1'
|
||||
);
|
||||
$query->setParameter('vipMaxId', 10);
|
||||
$query->setParameter('id', 100);
|
||||
$query->setFirstResult(null)->setMaxResults(null);
|
||||
|
||||
$paginator = new Paginator($query);
|
||||
|
||||
$getCountQuery = new ReflectionMethod($paginator, 'getCountQuery');
|
||||
|
||||
$getCountQuery->setAccessible(true);
|
||||
|
||||
$this->assertCount(2, $getCountQuery->invoke($paginator)->getParameters());
|
||||
$this->assertCount(3, $paginator);
|
||||
|
||||
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Query\SqlWalker');
|
||||
|
||||
$paginator = new Paginator($query);
|
||||
|
||||
// if select part of query is replaced with count(...) paginator should remove
|
||||
// parameters from query object not used in new query.
|
||||
$this->assertCount(1, $getCountQuery->invoke($paginator)->getParameters());
|
||||
$this->assertCount(3, $paginator);
|
||||
}
|
||||
|
||||
public function populate()
|
||||
{
|
||||
|
||||
@@ -48,8 +48,9 @@ class ProxiesLikeEntitiesTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
public function testPersistUpdate()
|
||||
{
|
||||
// Considering case (a)
|
||||
$proxy = $this->_em->getProxyFactory()->getProxy('Doctrine\Tests\Models\CMS\CmsUser', array('id' => null));
|
||||
$proxy = $this->_em->getProxyFactory()->getProxy('Doctrine\Tests\Models\CMS\CmsUser', array('id' => 123));
|
||||
$proxy->__isInitialized__ = true;
|
||||
$proxy->id = null;
|
||||
$proxy->username = 'ocra';
|
||||
$proxy->name = 'Marco';
|
||||
$this->_em->persist($proxy);
|
||||
|
||||
@@ -9,8 +9,10 @@ require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp() {
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if ($this->_em->getConnection()->getDatabasePlatform()->getName() !== 'postgresql') {
|
||||
$this->markTestSkipped('The ' . __CLASS__ .' requires the use of postgresql.');
|
||||
}
|
||||
@@ -19,6 +21,7 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
public function testPostgresMetadataSequenceIncrementedBy10()
|
||||
{
|
||||
$address = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress');
|
||||
|
||||
$this->assertEquals(1, $address->sequenceGeneratorDefinition['allocationSize']);
|
||||
}
|
||||
|
||||
@@ -97,7 +100,9 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$sql = $tool->getDropSchemaSQL($classes);
|
||||
|
||||
$this->assertEquals(14, count($sql));
|
||||
|
||||
$dropSequenceSQLs = 0;
|
||||
|
||||
foreach ($sql AS $stmt) {
|
||||
if (strpos($stmt, "DROP SEQUENCE") === 0) {
|
||||
$dropSequenceSQLs++;
|
||||
@@ -115,10 +120,6 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1657Screen'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1657Avatar'),
|
||||
);
|
||||
try {
|
||||
$this->_em->getConnection()->exec("CREATE SCHEMA stonewood");
|
||||
} catch(\Exception $e) {
|
||||
}
|
||||
|
||||
$tool = new SchemaTool($this->_em);
|
||||
$tool->createSchema($classes);
|
||||
|
||||
@@ -20,6 +20,7 @@ class DDC1360Test extends OrmFunctionalTestCase
|
||||
));
|
||||
|
||||
$this->assertEquals(array(
|
||||
'CREATE SCHEMA user',
|
||||
'CREATE TABLE "user"."user" (id INT NOT NULL, PRIMARY KEY(id))',
|
||||
'CREATE SEQUENCE "user"."user_id_seq" INCREMENT BY 1 MINVALUE 1 START 1',
|
||||
), $sql);
|
||||
|
||||
@@ -12,6 +12,12 @@ use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
|
||||
*/
|
||||
class DDC2074Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->useModelSet('ecommerce');
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testShouldNotScheduleDeletionOnClonedInstances()
|
||||
{
|
||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceProduct');
|
||||
@@ -26,4 +32,30 @@ class DDC2074Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->assertEquals(0, count($uow->getScheduledCollectionDeletions()));
|
||||
}
|
||||
}
|
||||
|
||||
public function testSavingClonedPersistentCollection()
|
||||
{
|
||||
$product = new ECommerceProduct();
|
||||
$category = new ECommerceCategory();
|
||||
$category->setName('foo');
|
||||
$product->addCategory($category);
|
||||
|
||||
$this->_em->persist($product);
|
||||
$this->_em->persist($category);
|
||||
$this->_em->flush();
|
||||
|
||||
$newProduct = clone $product;
|
||||
|
||||
$this->_em->persist($newProduct);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$product1 = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $product->getId());
|
||||
$product2 = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $newProduct->getId());
|
||||
|
||||
$this->assertCount(1, $product1->getCategories());
|
||||
$this->assertCount(1, $product2->getCategories());
|
||||
|
||||
$this->assertSame($product1->getCategories()->get(0), $product2->getCategories()->get(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-2645
|
||||
*/
|
||||
class DDC2645Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function testIssue()
|
||||
{
|
||||
$bar = new DDC2645Bar;
|
||||
$bar->id = 123;
|
||||
|
||||
$foo = new DDC2645Foo(1, $bar, 'Foo');
|
||||
$foo2 = new DDC2645Foo(1, $bar, 'Bar');
|
||||
|
||||
$this->_em->persist($bar);
|
||||
$this->_em->persist($foo);
|
||||
|
||||
$foo3 = $this->_em->merge($foo2);
|
||||
|
||||
$this->assertSame($foo, $foo3);
|
||||
$this->assertEquals('Bar', $foo->name);
|
||||
}
|
||||
}
|
||||
|
||||
/** @Entity */
|
||||
class DDC2645Foo
|
||||
{
|
||||
/** @Id @Column(type="integer") */
|
||||
private $id;
|
||||
|
||||
/** @Id @ManyToOne(targetEntity="DDC2645Bar") */
|
||||
private $bar;
|
||||
|
||||
/** @Column */
|
||||
public $name;
|
||||
|
||||
public function __construct($id, $bar, $name)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->bar = $bar;
|
||||
$this->name = $name;
|
||||
}
|
||||
}
|
||||
|
||||
/** @Entity */
|
||||
class DDC2645Bar
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue(strategy="NONE") */
|
||||
public $id;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\EventSubscriber;
|
||||
use Doctrine\ORM\Event\PreFlushEventArgs;
|
||||
|
||||
/**
|
||||
* @group DDC-2692
|
||||
*/
|
||||
class DDC2692Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function setup()
|
||||
{
|
||||
parent::setup();
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2692Foo'),
|
||||
));
|
||||
} catch(\Exception $e) {
|
||||
return;
|
||||
}
|
||||
$this->_em->clear();
|
||||
}
|
||||
|
||||
public function testIsListenerCalledOnlyOnceOnPreFlush()
|
||||
{
|
||||
$listener = $this->getMock('Doctrine\Tests\ORM\Functional\Ticket\DDC2692Listener', array('preFlush'));
|
||||
$listener->expects($this->once())->method('preFlush');
|
||||
|
||||
$this->_em->getEventManager()->addEventSubscriber($listener);
|
||||
|
||||
$this->_em->persist(new DDC2692Foo);
|
||||
$this->_em->persist(new DDC2692Foo);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @Entity @Table(name="ddc_2692_foo")
|
||||
*/
|
||||
class DDC2692Foo
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
}
|
||||
|
||||
class DDC2692Listener implements EventSubscriber {
|
||||
|
||||
public function getSubscribedEvents() {
|
||||
return array(\Doctrine\ORM\Events::preFlush);
|
||||
}
|
||||
|
||||
public function preFlush(PreFlushEventArgs $args) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
|
||||
/**
|
||||
* Functional tests for cascade remove with class table inheritance.
|
||||
*
|
||||
* @author Matthieu Napoli <matthieu@mnapoli.fr>
|
||||
*/
|
||||
class DDC2775Test extends OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->setUpEntitySchema(array(
|
||||
'Doctrine\Tests\ORM\Functional\Ticket\User',
|
||||
'Doctrine\Tests\ORM\Functional\Ticket\Role',
|
||||
'Doctrine\Tests\ORM\Functional\Ticket\AdminRole',
|
||||
'Doctrine\Tests\ORM\Functional\Ticket\Authorization',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-2775
|
||||
*/
|
||||
public function testIssueCascadeRemove()
|
||||
{
|
||||
$user = new User();
|
||||
|
||||
$role = new AdminRole();
|
||||
$user->addRole($role);
|
||||
|
||||
$authorization = new Authorization();
|
||||
$user->addAuthorization($authorization);
|
||||
$role->addAuthorization($authorization);
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
// Need to clear so that associations are lazy-loaded
|
||||
$this->_em->clear();
|
||||
|
||||
$user = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\User', $user->id);
|
||||
|
||||
$this->_em->remove($user);
|
||||
$this->_em->flush();
|
||||
|
||||
// With the bug, the second flush throws an error because the cascade remove didn't work correctly
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity @Table(name="ddc2775_role")
|
||||
* @InheritanceType("JOINED")
|
||||
* @DiscriminatorColumn(name="role_type", type="string")
|
||||
* @DiscriminatorMap({"admin"="AdminRole"})
|
||||
*/
|
||||
abstract class Role
|
||||
{
|
||||
/**
|
||||
* @Id @Column(type="integer")
|
||||
* @GeneratedValue
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="User", inversedBy="roles")
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="Authorization", mappedBy="role", cascade={"all"}, orphanRemoval=true)
|
||||
*/
|
||||
public $authorizations;
|
||||
|
||||
public function addAuthorization(Authorization $authorization)
|
||||
{
|
||||
$this->authorizations[] = $authorization;
|
||||
$authorization->role = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/** @Entity @Table(name="ddc2775_admin_role") */
|
||||
class AdminRole extends Role
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity @Table(name="ddc2775_authorizations")
|
||||
*/
|
||||
class Authorization
|
||||
{
|
||||
/**
|
||||
* @Id @Column(type="integer")
|
||||
* @GeneratedValue
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="User", inversedBy="authorizations")
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="Role", inversedBy="authorizations")
|
||||
*/
|
||||
public $role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity @Table(name="ddc2775_users")
|
||||
*/
|
||||
class User
|
||||
{
|
||||
/**
|
||||
* @Id @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="Role", mappedBy="user", cascade={"all"}, orphanRemoval=true)
|
||||
*/
|
||||
public $roles;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="Authorization", mappedBy="user", cascade={"all"}, orphanRemoval=true)
|
||||
*/
|
||||
public $authorizations;
|
||||
|
||||
public function addRole(Role $role)
|
||||
{
|
||||
$this->roles[] = $role;
|
||||
$role->user = $this;
|
||||
}
|
||||
|
||||
public function addAuthorization(Authorization $authorization)
|
||||
{
|
||||
$this->authorizations[] = $authorization;
|
||||
$authorization->user = $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
/**
|
||||
* Class DDC2895Test
|
||||
* @package Doctrine\Tests\ORM\Functional\Ticket
|
||||
* @author http://github.com/gwagner
|
||||
*/
|
||||
class DDC2895Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC2895'),
|
||||
));
|
||||
} catch(\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function testPostLoadOneToManyInheritance()
|
||||
{
|
||||
$cm = $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC2895');
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
"prePersist" => array("setLastModifiedPreUpdate"),
|
||||
"preUpdate" => array("setLastModifiedPreUpdate"),
|
||||
),
|
||||
$cm->lifecycleCallbacks
|
||||
);
|
||||
|
||||
$ddc2895 = new DDC2895();
|
||||
|
||||
$this->_em->persist($ddc2895);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
/** @var DDC2895 $ddc2895 */
|
||||
$ddc2895 = $this->_em->find(get_class($ddc2895), $ddc2895->id);
|
||||
|
||||
$this->assertNotNull($ddc2895->getLastModified());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @MappedSuperclass
|
||||
* @HasLifecycleCallbacks
|
||||
*/
|
||||
abstract class AbstractDDC2895
|
||||
{
|
||||
/**
|
||||
* @Column(name="last_modified", type="datetimetz", nullable=false)
|
||||
* @var \DateTime
|
||||
*/
|
||||
protected $lastModified;
|
||||
|
||||
/**
|
||||
* @PrePersist
|
||||
* @PreUpdate
|
||||
*/
|
||||
public function setLastModifiedPreUpdate()
|
||||
{
|
||||
$this->setLastModified(new \DateTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $lastModified
|
||||
*/
|
||||
public function setLastModified( $lastModified )
|
||||
{
|
||||
$this->lastModified = $lastModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getLastModified()
|
||||
{
|
||||
return $this->lastModified;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @HasLifecycleCallbacks
|
||||
*/
|
||||
class DDC2895 extends AbstractDDC2895
|
||||
{
|
||||
/** @Id @GeneratedValue @Column(type="integer") */
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
*/
|
||||
public function setId( $id )
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\ORM\Query;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-2931
|
||||
*/
|
||||
class DDC2931Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2931User'),
|
||||
));
|
||||
} catch (\Exception $e) {
|
||||
// no action needed - schema seems to be already in place
|
||||
}
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$first = new DDC2931User();
|
||||
$second = new DDC2931User();
|
||||
$third = new DDC2931User();
|
||||
|
||||
$second->parent = $first;
|
||||
$third->parent = $second;
|
||||
|
||||
$this->_em->persist($first);
|
||||
$this->_em->persist($second);
|
||||
$this->_em->persist($third);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$second = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC2931User', $second->id);
|
||||
|
||||
$this->assertSame(2, $second->getRank());
|
||||
}
|
||||
|
||||
public function testFetchJoinedEntitiesCanBeRefreshed()
|
||||
{
|
||||
$first = new DDC2931User();
|
||||
$second = new DDC2931User();
|
||||
$third = new DDC2931User();
|
||||
|
||||
$second->parent = $first;
|
||||
$third->parent = $second;
|
||||
|
||||
$first->value = 1;
|
||||
$second->value = 2;
|
||||
$third->value = 3;
|
||||
|
||||
$this->_em->persist($first);
|
||||
$this->_em->persist($second);
|
||||
$this->_em->persist($third);
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
$first->value = 4;
|
||||
$second->value = 5;
|
||||
$third->value = 6;
|
||||
|
||||
$refreshedSecond = $this
|
||||
->_em
|
||||
->createQuery(
|
||||
'SELECT e, p, c FROM '
|
||||
. __NAMESPACE__ . '\\DDC2931User e LEFT JOIN e.parent p LEFT JOIN e.child c WHERE e = :id'
|
||||
)
|
||||
->setParameter('id', $second)
|
||||
->setHint(Query::HINT_REFRESH, true)
|
||||
->getResult();
|
||||
|
||||
$this->assertCount(1, $refreshedSecond);
|
||||
$this->assertSame(1, $first->value);
|
||||
$this->assertSame(2, $second->value);
|
||||
$this->assertSame(3, $third->value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @Entity */
|
||||
class DDC2931User
|
||||
{
|
||||
|
||||
/** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */
|
||||
public $id;
|
||||
|
||||
/** @OneToOne(targetEntity="DDC2931User", inversedBy="child") */
|
||||
public $parent;
|
||||
|
||||
/** @OneToOne(targetEntity="DDC2931User", mappedBy="parent") */
|
||||
public $child;
|
||||
|
||||
/** @Column(type="integer") */
|
||||
public $value = 0;
|
||||
|
||||
/**
|
||||
* Return Rank recursively
|
||||
* My rank is 1 + rank of my parent
|
||||
* @return integer
|
||||
*/
|
||||
public function getRank()
|
||||
{
|
||||
return 1 + ($this->parent ? $this->parent->getRank() : 0);
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Types\ConversionException;
|
||||
use Doctrine\DBAL\Types\StringType;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
/**
|
||||
* @group DDC-2984
|
||||
*/
|
||||
class DDC2984Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if ( ! Type::hasType('ddc2984_domain_user_id')) {
|
||||
Type::addType(
|
||||
'ddc2984_domain_user_id',
|
||||
__NAMESPACE__ . '\DDC2984UserIdCustomDbalType'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2984User'),
|
||||
));
|
||||
} catch (\Exception $e) {
|
||||
// no action needed - schema seems to be already in place
|
||||
}
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$user = new DDC2984User(new DDC2984DomainUserId('unique_id_within_a_vo'));
|
||||
$user->applyName('Alex');
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush($user);
|
||||
|
||||
$repository = $this->_em->getRepository(__NAMESPACE__ . "\DDC2984User");
|
||||
|
||||
$sameUser = $repository->find(new DDC2984DomainUserId('unique_id_within_a_vo'));
|
||||
|
||||
//Until know, everything works as expected
|
||||
$this->assertTrue($user->sameIdentityAs($sameUser));
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
//After clearing the identity map, the UnitOfWork produces the warning described in DDC-2984
|
||||
$equalUser = $repository->find(new DDC2984DomainUserId('unique_id_within_a_vo'));
|
||||
|
||||
$this->assertNotSame($user, $equalUser);
|
||||
$this->assertTrue($user->sameIdentityAs($equalUser));
|
||||
}
|
||||
}
|
||||
|
||||
/** @Entity @Table(name="users") */
|
||||
class DDC2984User
|
||||
{
|
||||
/**
|
||||
* @Id @Column(type="ddc2984_domain_user_id")
|
||||
* @GeneratedValue(strategy="NONE")
|
||||
*
|
||||
* @var DDC2984DomainUserId
|
||||
*/
|
||||
private $userId;
|
||||
|
||||
/** @Column(type="string", length=50) */
|
||||
private $name;
|
||||
|
||||
public function __construct(DDC2984DomainUserId $aUserId)
|
||||
{
|
||||
$this->userId = $aUserId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DDC2984DomainUserId
|
||||
*/
|
||||
public function userId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function name()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function applyName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DDC2984User $other
|
||||
* @return bool
|
||||
*/
|
||||
public function sameIdentityAs(DDC2984User $other)
|
||||
{
|
||||
return $this->userId()->sameValueAs($other->userId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DDC2984DomainUserId ValueObject
|
||||
*
|
||||
* @author Alexander Miertsch <kontakt@codeliner.ws>
|
||||
*/
|
||||
class DDC2984DomainUserId
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $userIdString;
|
||||
|
||||
/**
|
||||
* @param string $aUserIdString
|
||||
*/
|
||||
public function __construct($aUserIdString)
|
||||
{
|
||||
$this->userIdString = $aUserIdString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toString()
|
||||
{
|
||||
return $this->userIdString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DDC2984DomainUserId $other
|
||||
* @return bool
|
||||
*/
|
||||
public function sameValueAs(DDC2984DomainUserId $other)
|
||||
{
|
||||
return $this->toString() === $other->toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class DDC2984UserIdCustomDbalType
|
||||
*
|
||||
* @author Alexander Miertsch <kontakt@codeliner.ws>
|
||||
*/
|
||||
class DDC2984UserIdCustomDbalType extends StringType
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'ddc2984_domain_user_id';
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function convertToPHPValue($value, AbstractPlatform $platform)
|
||||
{
|
||||
return ! empty($value)
|
||||
? new DDC2984DomainUserId($value)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
||||
{
|
||||
if (empty($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ( ! $value instanceof DDC2984DomainUserId) {
|
||||
throw ConversionException::conversionFailed($value, $this->getName());
|
||||
}
|
||||
|
||||
return $value->toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
|
||||
/**
|
||||
* @group DDC-2996
|
||||
*/
|
||||
class DDC2996Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function testIssue()
|
||||
{
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC2996User'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC2996UserPreference'),
|
||||
));
|
||||
|
||||
$pref = new DDC2996UserPreference();
|
||||
$pref->user = new DDC2996User();
|
||||
$pref->value = "foo";
|
||||
|
||||
$this->_em->persist($pref);
|
||||
$this->_em->persist($pref->user);
|
||||
$this->_em->flush();
|
||||
|
||||
$pref->value = "bar";
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertEquals(1, $pref->user->counter);
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$pref = $this->_em->find(__NAMESPACE__ . '\\DDC2996UserPreference', $pref->id);
|
||||
$this->assertEquals(1, $pref->user->counter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC2996User
|
||||
{
|
||||
/**
|
||||
* @Id @GeneratedValue @Column(type="integer")
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
public $counter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity @HasLifecycleCallbacks
|
||||
*/
|
||||
class DDC2996UserPreference
|
||||
{
|
||||
/**
|
||||
* @Id @GeneratedValue @Column(type="integer")
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @Column(type="string")
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC2996User")
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @PreFlush
|
||||
*/
|
||||
public function preFlush($event)
|
||||
{
|
||||
$em = $event->getEntityManager();
|
||||
$uow = $em->getUnitOfWork();
|
||||
|
||||
if ($uow->getOriginalEntityData($this->user)) {
|
||||
$this->user->counter++;
|
||||
$uow->recomputeSingleEntityChangeSet(
|
||||
$em->getClassMetadata(get_class($this->user)),
|
||||
$this->user
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
|
||||
/**
|
||||
* @group DDC-3033
|
||||
*/
|
||||
class DDC3033Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function testIssue()
|
||||
{
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC3033User'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC3033Product'),
|
||||
));
|
||||
|
||||
$user = new DDC3033User();
|
||||
$user->name = "Test User";
|
||||
$this->_em->persist($user);
|
||||
|
||||
$user2 = new DDC3033User();
|
||||
$user2->name = "Test User 2";
|
||||
$this->_em->persist($user2);
|
||||
|
||||
$product = new DDC3033Product();
|
||||
$product->title = "Test product";
|
||||
$product->buyers[] = $user;
|
||||
|
||||
$this->_em->persist($product);
|
||||
$this->_em->flush();
|
||||
|
||||
$product->title = "Test Change title";
|
||||
$product->buyers[] = $user2;
|
||||
|
||||
$this->_em->persist($product);
|
||||
$this->_em->flush();
|
||||
|
||||
$expect = array(
|
||||
'title' => array(
|
||||
0 => 'Test product',
|
||||
1 => 'Test Change title',
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertEquals($expect, $product->changeSet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Table
|
||||
* @Entity @HasLifecycleCallbacks
|
||||
*/
|
||||
class DDC3033Product
|
||||
{
|
||||
public $changeSet = array();
|
||||
|
||||
/**
|
||||
* @var integer $id
|
||||
*
|
||||
* @Column(name="id", type="integer")
|
||||
* @Id
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var string $title
|
||||
*
|
||||
* @Column(name="title", type="string", length=255)
|
||||
*/
|
||||
public $title;
|
||||
|
||||
/**
|
||||
* @ManyToMany(targetEntity="DDC3033User")
|
||||
* @JoinTable(
|
||||
* name="user_purchases_3033",
|
||||
* joinColumns={@JoinColumn(name="product_id", referencedColumnName="id")},
|
||||
* inverseJoinColumns={@JoinColumn(name="user_id", referencedColumnName="id")}
|
||||
* )
|
||||
*/
|
||||
public $buyers;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->buyers = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PreUpdate
|
||||
*/
|
||||
public function preUpdate(LifecycleEventArgs $eventArgs)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @PostUpdate
|
||||
*/
|
||||
public function postUpdate(LifecycleEventArgs $eventArgs)
|
||||
{
|
||||
$em = $eventArgs->getEntityManager();
|
||||
$uow = $em->getUnitOfWork();
|
||||
$entity = $eventArgs->getEntity();
|
||||
$classMetadata = $em->getClassMetadata(get_class($entity));
|
||||
|
||||
$uow->computeChangeSet($classMetadata, $entity);
|
||||
$this->changeSet = $uow->getEntityChangeSet($entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Table
|
||||
* @Entity @HasLifecycleCallbacks
|
||||
*/
|
||||
class DDC3033User
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @Column(name="id", type="integer")
|
||||
* @Id
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Column(name="title", type="string", length=255)
|
||||
*/
|
||||
public $name;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
use Doctrine\ORM\Event\OnFlushEventArgs;
|
||||
use Doctrine\ORM\Events;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
|
||||
/**
|
||||
* FlushEventTest
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class DDC3160Test extends OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp() {
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3160
|
||||
*/
|
||||
public function testNoUpdateOnInsert()
|
||||
{
|
||||
$listener = new DDC3160OnFlushListener();
|
||||
$this->_em->getEventManager()->addEventListener(Events::onFlush, $listener);
|
||||
|
||||
$user = new CmsUser;
|
||||
$user->username = 'romanb';
|
||||
$user->name = 'Roman';
|
||||
$user->status = 'Dev';
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->refresh($user);
|
||||
|
||||
$this->assertEquals('romanc', $user->username);
|
||||
$this->assertEquals(1, $listener->inserts);
|
||||
$this->assertEquals(0, $listener->updates);
|
||||
}
|
||||
}
|
||||
|
||||
class DDC3160OnFlushListener
|
||||
{
|
||||
public $inserts = 0;
|
||||
public $updates = 0;
|
||||
|
||||
public function onFlush(OnFlushEventArgs $args)
|
||||
{
|
||||
$em = $args->getEntityManager();
|
||||
$uow = $em->getUnitOfWork();
|
||||
|
||||
foreach ($uow->getScheduledEntityInsertions() as $entity) {
|
||||
$this->inserts++;
|
||||
if ($entity instanceof CmsUser) {
|
||||
$entity->username = 'romanc';
|
||||
$cm = $em->getClassMetadata(get_class($entity));
|
||||
$uow->recomputeSingleEntityChangeSet($cm, $entity);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($uow->getScheduledEntityUpdates() as $entity) {
|
||||
$this->updates++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class DDC742Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="users")
|
||||
* @Table(name="ddc742_users")
|
||||
*/
|
||||
class DDC742User
|
||||
{
|
||||
@@ -111,7 +111,7 @@ class DDC742User
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="comments")
|
||||
* @Table(name="ddc742_comments")
|
||||
*/
|
||||
class DDC742Comment
|
||||
{
|
||||
|
||||
@@ -1928,4 +1928,34 @@ class ObjectHydratorTest extends HydrationTestCase
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
|
||||
$hydrator->hydrateAll($stmt, $rsm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3076
|
||||
*
|
||||
* @expectedException \Doctrine\ORM\Internal\Hydration\HydrationException
|
||||
* @expectedExceptionMessage The discriminator value "subworker" is invalid. It must be one of "person", "manager", "employee".
|
||||
*/
|
||||
public function testInvalidDiscriminatorValueException()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\Company\CompanyPerson', 'p');
|
||||
|
||||
$rsm->addFieldResult('p', 'p__id', 'id');
|
||||
$rsm->addFieldResult('p', 'p__name', 'name');
|
||||
$rsm->addMetaResult('p', 'discr', 'discr');
|
||||
$rsm->setDiscriminatorColumn('p', 'discr');
|
||||
|
||||
$resultSet = array(
|
||||
array(
|
||||
'p__id' => '1',
|
||||
'p__name' => 'Fabio B. Silva',
|
||||
'discr' => 'subworker'
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
|
||||
$hydrator->hydrateAll($stmt, $rsm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,4 +58,34 @@ class SimpleObjectHydratorTest extends HydrationTestCase
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$this->assertEquals($result[0], $expectedEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3076
|
||||
*
|
||||
* @expectedException \Doctrine\ORM\Internal\Hydration\HydrationException
|
||||
* @expectedExceptionMessage The discriminator value "subworker" is invalid. It must be one of "person", "manager", "employee".
|
||||
*/
|
||||
public function testInvalidDiscriminatorValueException()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\Company\CompanyPerson', 'p');
|
||||
|
||||
$rsm->addFieldResult('p', 'p__id', 'id');
|
||||
$rsm->addFieldResult('p', 'p__name', 'name');
|
||||
$rsm->addMetaResult('p', 'discr', 'discr');
|
||||
$rsm->setDiscriminatorColumn('p', 'discr');
|
||||
|
||||
$resultSet = array(
|
||||
array(
|
||||
'p__id' => '1',
|
||||
'p__name' => 'Fabio B. Silva',
|
||||
'discr' => 'subworker'
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator($this->_em);
|
||||
$hydrator->hydrateAll($stmt, $rsm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,12 +187,32 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertTrue($class->fieldMappings['name']['nullable']);
|
||||
$this->assertTrue($class->fieldMappings['name']['unique']);
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testEntityTableNameAndInheritance
|
||||
* @param ClassMetadata $class
|
||||
*/
|
||||
public function testFieldOptions($class)
|
||||
{
|
||||
$expected = array('foo' => 'bar', 'baz' => array('key' => 'val'));
|
||||
$this->assertEquals($expected, $class->fieldMappings['name']['options']);
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testEntityTableNameAndInheritance
|
||||
* @param ClassMetadata $class
|
||||
*/
|
||||
public function testIdFieldOptions($class)
|
||||
{
|
||||
$this->assertEquals(array('foo' => 'bar'), $class->fieldMappings['id']['options']);
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testFieldMappings
|
||||
* @param ClassMetadata $class
|
||||
@@ -890,7 +910,7 @@ class User
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @Column(type="integer", options={"foo": "bar"})
|
||||
* @generatedValue(strategy="AUTO")
|
||||
* @SequenceGenerator(sequenceName="tablename_seq", initialValue=1, allocationSize=100)
|
||||
**/
|
||||
@@ -971,6 +991,7 @@ class User
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'columnName' => 'id',
|
||||
'options' => array('foo' => 'bar'),
|
||||
));
|
||||
$metadata->mapField(array(
|
||||
'fieldName' => 'name',
|
||||
|
||||
@@ -192,15 +192,38 @@ class ClassMetadataFactoryTest extends \Doctrine\Tests\OrmTestCase
|
||||
$rootMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\RootClass');
|
||||
}
|
||||
|
||||
protected function _createEntityManager($metadataDriver)
|
||||
public function testGetAllMetadataWorksWithBadConnection()
|
||||
{
|
||||
// DDC-3551
|
||||
$conn = $this->getMockBuilder('Doctrine\DBAL\Connection')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$mockDriver = new MetadataDriverMock();
|
||||
$em = $this->_createEntityManager($mockDriver, $conn);
|
||||
|
||||
$conn->expects($this->any())
|
||||
->method('getDatabasePlatform')
|
||||
->will($this->throwException(new \Exception('Exception thrown in test when calling getDatabasePlatform')));
|
||||
|
||||
$cmf = new ClassMetadataFactory();
|
||||
$cmf->setEntityManager($em);
|
||||
|
||||
// getting all the metadata should work, even if get DatabasePlatform blows up
|
||||
$metadata = $cmf->getAllMetadata();
|
||||
// this will just be an empty array - there was no error
|
||||
$this->assertEquals(array(), $metadata);
|
||||
}
|
||||
|
||||
protected function _createEntityManager($metadataDriver, $conn = null)
|
||||
{
|
||||
$driverMock = new DriverMock();
|
||||
$config = new \Doctrine\ORM\Configuration();
|
||||
$config->setProxyDir(__DIR__ . '/../../Proxies');
|
||||
$config->setProxyNamespace('Doctrine\Tests\Proxies');
|
||||
$eventManager = new EventManager();
|
||||
$conn = new ConnectionMock(array(), $driverMock, $config, $eventManager);
|
||||
$mockDriver = new MetadataDriverMock();
|
||||
if (!$conn) {
|
||||
$conn = new ConnectionMock(array(), $driverMock, $config, $eventManager);
|
||||
}
|
||||
$config->setMetadataDriverImpl($metadataDriver);
|
||||
|
||||
return EntityManagerMock::create($conn, $config, $eventManager);
|
||||
|
||||
@@ -1091,6 +1091,50 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
|
||||
|
||||
$this->assertEquals(array('sequenceName' => 'foo', 'quoted' => true), $cm->sequenceGeneratorDefinition);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-2700
|
||||
*/
|
||||
public function testIsIdentifierMappedSuperClass()
|
||||
{
|
||||
$class = new ClassMetadata(__NAMESPACE__ . '\\DDC2700MappedSuperClass');
|
||||
|
||||
$this->assertFalse($class->isIdentifier('foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3120
|
||||
*/
|
||||
public function testCanInstantiateInternalPhpClassSubclass()
|
||||
{
|
||||
$classMetadata = new ClassMetadata(__NAMESPACE__ . '\\MyArrayObjectEntity');
|
||||
|
||||
$classMetadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
|
||||
|
||||
$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 \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
|
||||
|
||||
$this->assertInstanceOf(__NAMESPACE__ . '\\MyArrayObjectEntity', $classMetadata->newInstance());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @MappedSuperclass
|
||||
*/
|
||||
class DDC2700MappedSuperClass
|
||||
{
|
||||
/** @Column */
|
||||
private $foo;
|
||||
}
|
||||
|
||||
class MyNamespacedNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy
|
||||
@@ -1118,3 +1162,7 @@ class MyPrefixNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy
|
||||
return strtolower($this->classToTableName($className)) . '_' . $propertyName;
|
||||
}
|
||||
}
|
||||
|
||||
class MyArrayObjectEntity extends \ArrayObject
|
||||
{
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ $metadata->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'columnName' => 'id',
|
||||
'options' => array('foo' => 'bar'),
|
||||
));
|
||||
$metadata->mapField(array(
|
||||
'fieldName' => 'name',
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
<id name="id" type="integer" column="id">
|
||||
<generator strategy="AUTO"/>
|
||||
<sequence-generator sequence-name="tablename_seq" allocation-size="100" initial-value="1" />
|
||||
<options>
|
||||
<option name="foo">bar</option>
|
||||
</options>
|
||||
</id>
|
||||
|
||||
<field name="name" column="name" type="string" length="50" nullable="true" unique="true">
|
||||
|
||||
@@ -16,6 +16,8 @@ Doctrine\Tests\ORM\Mapping\User:
|
||||
sequenceName: tablename_seq
|
||||
allocationSize: 100
|
||||
initialValue: 1
|
||||
options:
|
||||
foo: bar
|
||||
fields:
|
||||
name:
|
||||
type: string
|
||||
|
||||
@@ -592,12 +592,20 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @gorup DDC-1858
|
||||
* @group DDC-1858
|
||||
*/
|
||||
public function testHavingSupportIsNullExpression()
|
||||
{
|
||||
$this->assertValidDQL("SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u HAVING u.username IS NULL");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3018
|
||||
*/
|
||||
public function testNewLiteralExpression()
|
||||
{
|
||||
$this->assertValidDQL("SELECT new " . __NAMESPACE__ . "\\DummyStruct(u.id, 'foo', 1, true) FROM Doctrine\Tests\Models\CMS\CmsUser u");
|
||||
}
|
||||
}
|
||||
|
||||
/** @Entity */
|
||||
@@ -617,3 +625,10 @@ class DQLKeywordsModelGroup
|
||||
/** @Column */
|
||||
private $from;
|
||||
}
|
||||
|
||||
class DummyStruct
|
||||
{
|
||||
public function __construct($id, $arg1, $arg2, $arg3)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class QueryExpressionVisitorTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
$this->visitor = new QueryExpressionVisitor();
|
||||
$this->visitor = new QueryExpressionVisitor('o');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,22 +71,22 @@ class QueryExpressionVisitorTest extends \PHPUnit_Framework_TestCase
|
||||
$qb = new QueryBuilder();
|
||||
|
||||
return array(
|
||||
array($cb->eq('field', 'value'), $qb->eq('field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->neq('field', 'value'), $qb->neq('field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->eq('field', null), $qb->isNull('field')),
|
||||
array($cb->neq('field', null), $qb->isNotNull('field')),
|
||||
array($cb->isNull('field'), $qb->isNull('field')),
|
||||
array($cb->eq('field', 'value'), $qb->eq('o.field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->neq('field', 'value'), $qb->neq('o.field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->eq('field', null), $qb->isNull('o.field')),
|
||||
array($cb->neq('field', null), $qb->isNotNull('o.field')),
|
||||
array($cb->isNull('field'), $qb->isNull('o.field')),
|
||||
|
||||
array($cb->gt('field', 'value'), $qb->gt('field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->gte('field', 'value'), $qb->gte('field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->lt('field', 'value'), $qb->lt('field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->lte('field', 'value'), $qb->lte('field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->gt('field', 'value'), $qb->gt('o.field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->gte('field', 'value'), $qb->gte('o.field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->lt('field', 'value'), $qb->lt('o.field', ':field'), new Parameter('field', 'value')),
|
||||
array($cb->lte('field', 'value'), $qb->lte('o.field', ':field'), new Parameter('field', 'value')),
|
||||
|
||||
array($cb->in('field', array('value')), $qb->in('field', ':field'), new Parameter('field', array('value'))),
|
||||
array($cb->notIn('field', array('value')), $qb->notIn('field', ':field'), new Parameter('field', array('value'))),
|
||||
array($cb->in('field', array('value')), $qb->in('o.field', ':field'), new Parameter('field', array('value'))),
|
||||
array($cb->notIn('field', array('value')), $qb->notIn('o.field', ':field'), new Parameter('field', array('value'))),
|
||||
|
||||
// Test parameter conversion
|
||||
array($cb->eq('object.field', 'value'), $qb->eq('object.field', ':object_field'), new Parameter('object_field', 'value')),
|
||||
array($cb->eq('object.field', 'value'), $qb->eq('o.object.field', ':object_field'), new Parameter('object_field', 'value')),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1993,11 +1993,11 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
$connMock->setDatabasePlatform(new \Doctrine\DBAL\Platforms\SQLServerPlatform());
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CONCAT(u.name, u.status, 's') = ?1",
|
||||
"SELECT c0_.id AS id0 FROM cms_users c0_ WITH (NOLOCK) WHERE (c0_.name + c0_.status + 's') = ?"
|
||||
"SELECT c0_.id AS id0 FROM cms_users c0_ WHERE (c0_.name + c0_.status + 's') = ?"
|
||||
);
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT CONCAT(u.id, u.name, u.status) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1",
|
||||
"SELECT (c0_.id + c0_.name + c0_.status) AS sclr0 FROM cms_users c0_ WITH (NOLOCK) WHERE c0_.id = ?"
|
||||
"SELECT (c0_.id + c0_.name + c0_.status) AS sclr0 FROM cms_users c0_ WHERE c0_.id = ?"
|
||||
);
|
||||
|
||||
$connMock->setDatabasePlatform($orgPlatform);
|
||||
@@ -2058,7 +2058,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT e.id FROM Doctrine\Tests\Models\Company\CompanyOrganization o JOIN o.events e WITH e.id = ?1',
|
||||
'SELECT c0_.id AS id0 FROM company_organizations c1_ INNER JOIN company_events c0_ ON c1_.id = c0_.org_id AND (c0_.id = ?) LEFT JOIN company_auctions c2_ ON c0_.id = c2_.id LEFT JOIN company_raffles c3_ ON c0_.id = c3_.id',
|
||||
'SELECT c0_.id AS id0 FROM company_organizations c1_ INNER JOIN (company_events c0_ LEFT JOIN company_auctions c2_ ON c0_.id = c2_.id LEFT JOIN company_raffles c3_ ON c0_.id = c3_.id) ON c1_.id = c0_.org_id AND (c0_.id = ?)',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -402,30 +402,39 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
|
||||
public function testAddCriteriaWhere()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder();
|
||||
$qb->select('u')
|
||||
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
|
||||
$criteria = new Criteria();
|
||||
$criteria->where($criteria->expr()->eq('field', 'value'));
|
||||
|
||||
$qb->addCriteria($criteria);
|
||||
|
||||
$this->assertEquals('field = :field', (string) $qb->getDQLPart('where'));
|
||||
$this->assertEquals('u.field = :field', (string) $qb->getDQLPart('where'));
|
||||
$this->assertNotNull($qb->getParameter('field'));
|
||||
}
|
||||
|
||||
public function testAddCriteriaOrder()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder();
|
||||
$qb->select('u')
|
||||
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
|
||||
$criteria = new Criteria();
|
||||
$criteria->orderBy(array('field' => Criteria::DESC));
|
||||
|
||||
$qb->addCriteria($criteria);
|
||||
|
||||
$this->assertCount(1, $orderBy = $qb->getDQLPart('orderBy'));
|
||||
$this->assertEquals('field DESC', (string) $orderBy[0]);
|
||||
$this->assertEquals('u.field DESC', (string) $orderBy[0]);
|
||||
}
|
||||
|
||||
public function testAddCriteriaLimit()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder();
|
||||
$qb->select('u')
|
||||
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
|
||||
$criteria = new Criteria();
|
||||
$criteria->setFirstResult(2);
|
||||
$criteria->setMaxResults(10);
|
||||
@@ -439,7 +448,11 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
|
||||
public function testAddCriteriaUndefinedLimit()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder();
|
||||
$qb->setFirstResult(2)->setMaxResults(10);
|
||||
$qb->select('u')
|
||||
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
|
||||
->setFirstResult(2)
|
||||
->setMaxResults(10);
|
||||
|
||||
$criteria = new Criteria();
|
||||
|
||||
$qb->addCriteria($criteria);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Doctrine\Tests\ORM\Tools;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\ORM\Tools\SchemaTool,
|
||||
Doctrine\ORM\Tools\EntityGenerator,
|
||||
Doctrine\ORM\Tools\Export\ClassMetadataExporter,
|
||||
@@ -55,7 +56,7 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
|
||||
$metadata->table['uniqueConstraints']['name_uniq'] = array('columns' => array('name'));
|
||||
$metadata->table['indexes']['status_idx'] = array('columns' => array('status'));
|
||||
$metadata->mapField(array('fieldName' => 'name', 'type' => 'string'));
|
||||
$metadata->mapField(array('fieldName' => 'status', 'type' => 'string', 'default' => 'published'));
|
||||
$metadata->mapField(array('fieldName' => 'status', 'type' => 'string', 'options' => array('default' => 'published')));
|
||||
$metadata->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true));
|
||||
$metadata->mapOneToOne(array('fieldName' => 'author', 'targetEntity' => 'Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor', 'mappedBy' => 'book'));
|
||||
$joinColumns = array(
|
||||
@@ -454,6 +455,97 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertEquals($value, $entity->{$getter}());
|
||||
}
|
||||
|
||||
/**
|
||||
* @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'));
|
||||
}
|
||||
|
||||
public function testRegenerateEntityClass()
|
||||
{
|
||||
$metadata = $this->generateBookEntityFixture();
|
||||
$this->loadEntityClass($metadata);
|
||||
|
||||
$className = basename(str_replace('\\', '/', $metadata->name));
|
||||
$path = $this->_tmpDir . '/' . $this->_namespace . '/' . $className . '.php';
|
||||
$classTest = file_get_contents($path);
|
||||
|
||||
$this->_generator->setRegenerateEntityIfExists(true);
|
||||
$this->_generator->setBackupExisting(false);
|
||||
|
||||
$this->_generator->writeEntityClass($metadata, $this->_tmpDir);
|
||||
$classNew = file_get_contents($path);
|
||||
|
||||
$this->assertSame($classTest,$classNew);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
@@ -552,9 +644,32 @@ class
|
||||
',
|
||||
array('Foo\Bar\Baz'),
|
||||
),
|
||||
array(
|
||||
'
|
||||
<?php namespace Foo\Bar; class Baz {
|
||||
public static function someMethod(){
|
||||
return self::class;
|
||||
}
|
||||
}
|
||||
',
|
||||
array('Foo\Bar\Baz'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassMetadataInfo $metadata
|
||||
*/
|
||||
private function loadEntityClass(ClassMetadataInfo $metadata)
|
||||
{
|
||||
$className = basename(str_replace('\\', '/', $metadata->name));
|
||||
$path = $this->_tmpDir . '/' . $this->_namespace . '/' . $className . '.php';
|
||||
|
||||
$this->assertFileExists($path);
|
||||
|
||||
require_once $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param \ReflectionProperty $property
|
||||
|
||||
@@ -209,6 +209,27 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testExportDirectoryAndFilesAreCreated
|
||||
*/
|
||||
public function testFieldsAreProperlySerialized()
|
||||
{
|
||||
$type = $this->_getType();
|
||||
if ($type == 'xml') {
|
||||
$xml = simplexml_load_file(__DIR__ . '/export/'.$type.'/Doctrine.Tests.ORM.Tools.Export.ExportedUser.dcm.xml');
|
||||
|
||||
$xml->registerXPathNamespace("d", "http://doctrine-project.org/schemas/orm/doctrine-mapping");
|
||||
$nodes = $xml->xpath("/d:doctrine-mapping/d:entity/d:field[@name='name' and @type='string' and @nullable='true']");
|
||||
$this->assertEquals(1, count($nodes));
|
||||
|
||||
$nodes = $xml->xpath("/d:doctrine-mapping/d:entity/d:field[@name='name' and @type='string' and @unique='true']");
|
||||
$this->assertEquals(1, count($nodes));
|
||||
}
|
||||
else {
|
||||
$this->markTestSkipped('Test available only for '.$type.' driver');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testFieldsAreExported
|
||||
* @param ClassMetadataInfo $class
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace Doctrine\Tests\ORM\Tools\Pagination;
|
||||
|
||||
use Doctrine\DBAL\Platforms\MySqlPlatform;
|
||||
use Doctrine\DBAL\Platforms\OraclePlatform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
|
||||
use Doctrine\ORM\Query;
|
||||
|
||||
class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
@@ -22,7 +25,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
public function testLimitSubqueryWithSortPg()
|
||||
{
|
||||
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
|
||||
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a ORDER BY p.title');
|
||||
@@ -39,7 +42,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
public function testLimitSubqueryWithScalarSortPg()
|
||||
{
|
||||
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
|
||||
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT u, g, COUNT(g.id) AS g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity'
|
||||
@@ -58,7 +61,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
public function testLimitSubqueryWithMixedSortPg()
|
||||
{
|
||||
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
|
||||
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT u, g, COUNT(g.id) AS g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity, u.id DESC'
|
||||
@@ -77,7 +80,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
public function testLimitSubqueryWithHiddenScalarSortPg()
|
||||
{
|
||||
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
|
||||
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT u, g, COUNT(g.id) AS hidden g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity, u.id DESC'
|
||||
@@ -96,7 +99,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
public function testLimitSubqueryPg()
|
||||
{
|
||||
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new PostgreSqlPlatform);
|
||||
|
||||
$this->testLimitSubquery();
|
||||
|
||||
@@ -106,7 +109,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
public function testLimitSubqueryWithSortOracle()
|
||||
{
|
||||
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\OraclePlatform);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform);
|
||||
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a ORDER BY p.title');
|
||||
@@ -124,7 +127,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
public function testLimitSubqueryWithScalarSortOracle()
|
||||
{
|
||||
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\OraclePlatform);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform);
|
||||
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT u, g, COUNT(g.id) AS g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity'
|
||||
@@ -144,7 +147,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
public function testLimitSubqueryWithMixedSortOracle()
|
||||
{
|
||||
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\OraclePlatform);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform);
|
||||
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT u, g, COUNT(g.id) AS g_quantity FROM Doctrine\Tests\ORM\Tools\Pagination\User u JOIN u.groups g ORDER BY g_quantity, u.id DESC'
|
||||
@@ -164,7 +167,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
public function testLimitSubqueryOracle()
|
||||
{
|
||||
$odp = $this->entityManager->getConnection()->getDatabasePlatform();
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\OraclePlatform);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new OraclePlatform);
|
||||
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a');
|
||||
@@ -179,7 +182,7 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
$this->entityManager->getConnection()->setDatabasePlatform($odp);
|
||||
}
|
||||
|
||||
public function testCountQuery_MixedResultsWithName()
|
||||
public function testCountQueryMixedResultsWithName()
|
||||
{
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT a, sum(a.name) as foo FROM Doctrine\Tests\ORM\Tools\Pagination\Author a');
|
||||
@@ -190,5 +193,40 @@ class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
"SELECT DISTINCT id0 FROM (SELECT a0_.id AS id0, a0_.name AS name1, sum(a0_.name) AS sclr2 FROM Author a0_) dctrn_result", $limitQuery->getSql()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3336
|
||||
*/
|
||||
public function testCountQueryWithArithmeticOrderByCondition()
|
||||
{
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT a FROM Doctrine\Tests\ORM\Tools\Pagination\Author a ORDER BY (1 - 1000) * 1 DESC'
|
||||
);
|
||||
$this->entityManager->getConnection()->setDatabasePlatform(new MySqlPlatform());
|
||||
|
||||
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
|
||||
|
||||
$this->assertSame(
|
||||
'SELECT DISTINCT id0 FROM (SELECT a0_.id AS id0, a0_.name AS name1 FROM Author a0_ ORDER BY (1 - 1000) * 1 DESC) dctrn_result',
|
||||
$query->getSQL()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3434
|
||||
*/
|
||||
public function testLimitSubqueryWithHiddenSelectionInOrderBy()
|
||||
{
|
||||
$query = $this->entityManager->createQuery(
|
||||
'SELECT a, a.name AS HIDDEN ord FROM Doctrine\Tests\ORM\Tools\Pagination\Author a ORDER BY ord DESC'
|
||||
);
|
||||
|
||||
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\LimitSubqueryOutputWalker');
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT DISTINCT id0, name2 FROM (SELECT a0_.id AS id0, a0_.name AS name1, a0_.name AS name2 FROM Author a0_ ORDER BY name2 DESC) dctrn_result ORDER BY name2 DESC',
|
||||
$query->getSql()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ use Doctrine\Tests\OrmTestCase;
|
||||
|
||||
abstract class PaginationTestCase extends OrmTestCase
|
||||
{
|
||||
/**
|
||||
* @var \Doctrine\ORM\EntityManagerInterface
|
||||
*/
|
||||
public $entityManager;
|
||||
|
||||
public function setUp()
|
||||
|
||||
@@ -101,6 +101,23 @@ class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertEquals(count($classes), $listener->tableCalls);
|
||||
$this->assertTrue($listener->schemaCalled);
|
||||
}
|
||||
|
||||
public function testNullDefaultNotAddedToCustomSchemaOptions()
|
||||
{
|
||||
$em = $this->_getTestEntityManager();
|
||||
$schemaTool = new SchemaTool($em);
|
||||
|
||||
$classes = array(
|
||||
$em->getClassMetadata('Doctrine\Tests\Models\NullDefault\NullDefaultColumn'),
|
||||
);
|
||||
|
||||
$customSchemaOptions = $schemaTool->getSchemaFromMetadata($classes)
|
||||
->getTable('NullDefaultColumn')
|
||||
->getColumn('nullDefault')
|
||||
->getCustomSchemaOptions();
|
||||
|
||||
$this->assertSame(array(), $customSchemaOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -229,6 +229,25 @@ class UnitOfWorkTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
$this->_unitOfWork->lock(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3619
|
||||
* @group 1338
|
||||
*/
|
||||
public function testRemovedAndRePersistedEntitiesAreInTheIdentityMapAndAreNotGarbageCollected()
|
||||
{
|
||||
$entity = new ForumUser();
|
||||
$entity->id = 123;
|
||||
|
||||
$this->_unitOfWork->registerManaged($entity, array('id' => 123), array());
|
||||
$this->assertTrue($this->_unitOfWork->isInIdentityMap($entity));
|
||||
|
||||
$this->_unitOfWork->remove($entity);
|
||||
$this->assertFalse($this->_unitOfWork->isInIdentityMap($entity));
|
||||
|
||||
$this->_unitOfWork->persist($entity);
|
||||
$this->assertTrue($this->_unitOfWork->isInIdentityMap($entity));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -139,6 +139,10 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
'Doctrine\Tests\Models\StockExchange\Stock',
|
||||
'Doctrine\Tests\Models\StockExchange\Market',
|
||||
),
|
||||
'tweet' => array(
|
||||
'Doctrine\Tests\Models\Tweet\Tweet',
|
||||
'Doctrine\Tests\Models\Tweet\User',
|
||||
),
|
||||
'legacy' => array(
|
||||
'Doctrine\Tests\Models\Legacy\LegacyUser',
|
||||
'Doctrine\Tests\Models\Legacy\LegacyUserReference',
|
||||
@@ -162,6 +166,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
'Doctrine\Tests\Models\Taxi\Car',
|
||||
'Doctrine\Tests\Models\Taxi\Driver',
|
||||
),
|
||||
'tweet' => array(
|
||||
'Doctrine\Tests\Models\Tweet\User',
|
||||
'Doctrine\Tests\Models\Tweet\Tweet',
|
||||
'Doctrine\Tests\Models\Tweet\UserList',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -269,6 +278,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
$conn->executeUpdate('DELETE FROM exchange_stocks');
|
||||
$conn->executeUpdate('DELETE FROM exchange_markets');
|
||||
}
|
||||
if (isset($this->_usedModelSets['tweet'])) {
|
||||
$conn->executeUpdate('DELETE FROM tweet_tweet');
|
||||
$conn->executeUpdate('DELETE FROM tweet_user_list');
|
||||
$conn->executeUpdate('DELETE FROM tweet_user');
|
||||
}
|
||||
if (isset($this->_usedModelSets['legacy'])) {
|
||||
$conn->executeUpdate('DELETE FROM legacy_users_cars');
|
||||
$conn->executeUpdate('DELETE FROM legacy_users_reference');
|
||||
@@ -297,6 +311,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
$conn->executeUpdate('DELETE FROM taxi_driver');
|
||||
}
|
||||
|
||||
if (isset($this->_usedModelSets['tweet'])) {
|
||||
$conn->executeUpdate('DELETE FROM tweet_tweet');
|
||||
$conn->executeUpdate('DELETE FROM tweet_user_list');
|
||||
$conn->executeUpdate('DELETE FROM tweet_user');
|
||||
}
|
||||
|
||||
$this->_em->clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
<var name="tmpdb_port" value="3306"/>
|
||||
</php>
|
||||
|
||||
<logging>
|
||||
<log type="coverage-clover" target="../../build/logs/clover.xml"/>
|
||||
</logging>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Doctrine ORM Test Suite">
|
||||
<directory>./../Doctrine/Tests/ORM</directory>
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
<var name="tmpdb_port" value="5432"/>
|
||||
</php>
|
||||
|
||||
<logging>
|
||||
<log type="coverage-clover" target="../../build/logs/clover.xml"/>
|
||||
</logging>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Doctrine ORM Test Suite">
|
||||
<directory>./../Doctrine/Tests/ORM</directory>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<phpunit>
|
||||
|
||||
<logging>
|
||||
<log type="coverage-clover" target="../../build/logs/clover.xml"/>
|
||||
</logging>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Doctrine ORM Test Suite">
|
||||
<directory>./../Doctrine/Tests/ORM</directory>
|
||||
|
||||
Reference in New Issue
Block a user