Compare commits

..

118 Commits

Author SHA1 Message Date
Luís Cobucci 93103f44a3 Preparing v2.5.13 release 2017-11-28 00:25:55 +01:00
Luís Cobucci ffdb769564 Merge pull request #6818 from vkurdin/patch-1
BasicEntityPersister::count() return type fix
2017-11-27 23:08:51 +01:00
Vasiliy Kurdin 95344d019f BasicEntityPersister::count() return type fix
Resolve #6810 by casting return value to integer
2017-11-27 22:21:04 +01:00
Luís Cobucci 640d9af50f Merge pull request #6852 from gigi/2.5
Backport #6167 from 2.6 to 2.5.x branch
2017-11-27 22:12:53 +01:00
Alexey Snigirev a23e909158 #6167 - code cleanup for 2.5.x version 2017-11-27 14:58:44 +02:00
Marco Pivetta a857a610db #6167 #6168 rewrote SequenceGeneratorTest for better readability and error messages
(cherry picked from commit a97c265)
2017-11-27 12:28:35 +02:00
Marco Pivetta f0006eb42d #6167 #6168 - better connection mock documentation/docblocks/return-types
(cherry picked from commit 462481e)
2017-11-27 12:26:27 +02:00
Marco Pivetta 7ea97e69ca #6167 #6168 - clarifying on the reasoning why query is used instead of fetchColumn
(cherry picked from commit d2be4a2)
2017-11-27 12:24:31 +02:00
Michał Kurzeja de4b40b29f #6167 Code review updates, better readability
(cherry picked from commit 571115c)
2017-11-27 12:24:28 +02:00
Michał Kurzeja e21217dd0e #6167 - tests - throw exception if wrong method used to get sequence nextval
(cherry picked from commit 71b040c)
2017-11-27 12:24:23 +02:00
Michał Kurzeja b82aef2748 #6167 - fixed tests and added info why query is used in SequenceGenerator
(cherry picked from commit edffb4d)
2017-11-27 12:24:17 +02:00
Michał Kurzeja 44b3405714 Fixes #6167 - nextval issue on master-slave PostgreSQL setup
(cherry picked from commit 60b6073)
2017-11-27 12:22:54 +02:00
Luís Cobucci e874d93f61 Merge branch 'backport/bugfix/xml_sequence_params' into 2.5
Backporting: https://github.com/doctrine/doctrine2/pull/6683
2017-11-26 16:46:56 +01:00
Sasha Alex Romanenko bb31472727 Enforce sequence XSD requirement
Supply default values for allocationSize and initialValue optional parameters.

Related to: https://github.com/doctrine/doctrine2/issues/6682
2017-11-26 16:36:51 +01:00
Luís Cobucci fd72aa08d2 Merge branch 'backport/DDC288' into 2.5
Backporting: https://github.com/doctrine/doctrine2/pull/6740
2017-11-26 14:15:46 +01:00
Mathieu Duplouy 21f73cf923 Add operator to walkComparison output 2017-11-26 14:08:23 +01:00
Mathieu Duplouy 2701f5058e Add failing test for DCOM-288
Reported on: https://github.com/doctrine/common/issues/600
2017-11-26 14:07:58 +01:00
Luís Cobucci 4bd2f68483 Merge branch 'backport/cache-namespace-fix' into 2.5
Backporting: https://github.com/doctrine/doctrine2/pull/6848
Backporting: https://github.com/doctrine/doctrine2/pull/5904
2017-11-26 13:22:59 +01:00
Jan Jakes 823da6d839 Fix overwriting explicit cache namespace 2017-11-26 12:59:53 +01:00
Luís Cobucci 6318796965 Fix incorrect arguments on SetupTest
Which was only caught by adding proper type declaration on private
methods.
2017-11-26 12:38:01 +01:00
Luís Cobucci c811c3ac84 Merge branch 'backport/ticket/6699' into 2.5
Backporting: https://github.com/doctrine/doctrine2/pull/6705
2017-11-24 02:43:33 +01:00
Luís Cobucci aba62edcc8 Fix parameter name comparison in QueryBuilder#setParameter() with different types 2017-11-24 02:37:13 +01:00
Michael Moravec 0b4e5b42e1 Fix parameter name comparison in AbstractQuery#setParameter() with different types 2017-11-24 02:35:10 +01:00
Michael Moravec 3d4f236052 Add failing test for #6699 2017-11-24 02:31:48 +01:00
Luís Cobucci 049470c787 Merge pull request #6821 from remicollet/issue-count
For PHP 7.2
2017-11-12 12:25:46 +01:00
Remi Collet cfaad4fedc fix skip condition for APC 2017-11-10 15:54:09 +01:00
Remi Collet e8a89c3bc3 Fix ReflectionException: Given object is not an instance of the class this property was declared in 2017-11-10 15:54:04 +01:00
Remi Collet 497be59f5c fix for 7.2, ensure mocked ParserResult::getParameterMappings returns an array 2017-11-10 15:53:18 +01:00
Jonathan H. Wage e1b851f2e9 Bumping development version to v2.5.13-DEV 2017-10-23 13:26:03 -05:00
Jonathan H. Wage 984535cadc Preparing v2.5.12 release 2017-10-23 13:21:04 -05:00
Jonathan H. Wage 35a579efdc Merge pull request #6733 from fabpot/patch-2
Allow Symfony 4
2017-10-23 12:50:36 -05:00
Fabien Potencier a2b4e5b293 Allow Symfony 4 2017-09-27 15:33:54 -07:00
Marco Pivetta 24d95796bb Bumping development version to v2.5.12-DEV 2017-09-18 08:52:10 +02:00
Marco Pivetta 249b737094 Preparing v2.5.11 release 2017-09-18 08:50:20 +02:00
Marco Pivetta 36dc28d43e Merge pull request #6635 from davidbarratt/instantiator
Allow installation of `doctrine/instantiator:^1.0.1`
2017-08-19 18:47:32 +02:00
David Barratt 0ec9e53c8d Fix doctrine/instantiator constraint
The current constraint prevents doctrine from being installed on PHP 7.1
2017-08-19 11:51:46 -04:00
Marco Pivetta aa80f6c0b5 Removed PHPUnit 5.6+ API usage 2017-08-18 21:24:47 +02:00
Marco Pivetta fd6d4890c4 Bumping development release to 2.5.11-DEV 2017-08-18 21:23:23 +02:00
Marco Pivetta c78afd5172 Preparing v2.5.10 release 2017-08-18 21:17:35 +02:00
Marco Pivetta fb7b78c004 Merge branch 'fix/#6633-#3788-avoid-xml-external-entity-loading-errors-in-xml-mapping-driver-2.5' into 2.5
Backport #6633
Backport #3788
2017-08-18 21:12:12 +02:00
Marco Pivetta 0de69e5a80 #6633 #3788 documenting why simplexml_load_file() was not used 2017-08-18 21:10:45 +02:00
Aljosha Papsch d7e1f883d8 XmlDriver: Avoid PHP bug #62577 by avoiding simplexml_load_file.
Doctrine is affected by PHP bug #62577. simplexml_load_file is not
able to load files if libxml_disable_entity_loader(true) has been
called. simplexml_load_file fails with the message:

I/O warning : failed to load external entity "/my/mappings/my_entity.dcm.xml"
in /path-to/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php on line 711

This error occurs even if there are no external entities in the XML file.

Waiting for the PHP bug to be resolved is infeasible, because it is
unresolved since years. Therefore Doctrine needs to circumvent the bug
by replacing simplexml_load_file with simplexml_load_string while getting
the file contents itself. simplexml_load_string is not affected by the
PHP bug.
2017-08-18 21:10:11 +02:00
Marco Pivetta 82e0d7e21a Removing ::class meta-constant for tests that need to run against my grandparents' PHP 2017-08-16 20:06:14 +02:00
Marco Pivetta 26880983fc Removing ::class meta-constant for tests that need to run against my grandparents' PHP 2017-08-16 19:24:39 +02:00
Marco Pivetta d9899732ca Bumping development release to v2.5.10DEV 2017-08-16 15:30:59 +02:00
Marco Pivetta 4f96fc62ce Preparing v2.5.9 release 2017-08-16 15:30:32 +02:00
Marco Pivetta 6184343fd5 Merge branch 'fix/#6626-skip-proxy-generation-for-embeddable-classes-2.5' into 2.5
Backport #6626
Backport #6625
2017-08-16 15:21:29 +02:00
Marco Pivetta ee22be27a5 #6625 #6626 removing PHP 5.3 incompatibilities (required for backport) 2017-08-16 15:21:14 +02:00
Marco Pivetta 8f77210955 #6626 #6625 minor CS fixes (removed useless assignments) 2017-08-16 15:20:10 +02:00
Issei.M f736acc8f5 Replace double quote with single quote 2017-08-16 15:20:01 +02:00
Issei.M f1534610e1 Fix CS / Add annotation 2017-08-16 15:18:15 +02:00
Issei.M 6622bbbbf3 Skip embeddable classes proxy generation 2017-08-16 15:18:04 +02:00
Marco Pivetta 1554af0c07 Merge branch 'fix/#6623-#1515-ensure-abstracthydrator-hydrateall-cleans-up-on-unit-of-work-clear-2.5' into 2.5
Close #6623
2017-08-16 14:50:13 +02:00
Nikolas Tsiongas 814aa9f322 fix AbstractHydrator addEventListener on hydrateAll() 2017-08-16 14:49:22 +02:00
Marco Pivetta f311dd1dd1 Bumping development version to v2.5.9-DEV 2017-08-13 20:47:26 +02:00
Marco Pivetta e3aa3f2d1d Preparing v2.5.8 release 2017-08-13 20:46:56 +02:00
Marco Pivetta c83f479633 Merge pull request #6621 from Powerhamster/patch-1
fixed undefined variable
2017-08-13 20:27:18 +02:00
Thomas Rothe 741f1db198 fixed undefined variable
changed $conditions to $condition so $isConditionalJoin is working
2017-08-12 11:33:11 +02:00
Marco Pivetta 22546a3811 Correcting connection existence in tearDown operations 2017-08-11 23:28:20 +02:00
Marco Pivetta efa058bd8f If no connection was enstablished, skip the tearDown operations 2017-08-11 22:56:02 +02:00
Marco Pivetta 767577cec6 Removing ::class pseudo-constant usage 2017-08-11 22:49:46 +02:00
Marco Pivetta c0f593e422 Removing ::class syntax to make dinosaurs run against this codebase too 2017-08-11 22:22:50 +02:00
Marco Pivetta d89d238594 Merge branch 'fix/#6464-#6475-correct-SQL-generated-with-JTI-and-WITH-condition-2.5' into 2.5
Backport #6464
Backport #6475
2017-08-11 21:43:05 +02:00
Marco Pivetta 2337b7aedd #6464 #6475 cleaning up test - removed invalid fetch join, CS 2017-08-11 21:41:05 +02:00
Stefan Siegl 9e6f061bfb #6464 code review updates 2017-08-11 21:40:53 +02:00
Stefan Siegl bf1188127e generate nested join sql for CTIs, closes #6464 2017-08-11 21:40:16 +02:00
Stefan Siegl c73ec2aa76 #6464 add test 2017-08-11 21:39:45 +02:00
Marco Pivetta 095611c4b6 Merge branch 'fix/#6614-clean-modified-collection-causing-double-dirty-object-persistence-2.5' into 2.5
Backport #6613
Backport #6614
Backport #6616
2017-08-11 21:25:27 +02:00
Marco Pivetta 96c6f4cf1d #6613 #6614 #6616 removed unused import 2017-08-11 21:25:10 +02:00
Marco Pivetta 5cacb6e14f #6613 #6614 #6616 minor performance optimisations around the new restoreNewObjectsInDirtyCollection implementation 2017-08-11 21:23:58 +02:00
Marco Pivetta ab63628960 #6613 #6614 #6616 removing DDC6613 test, which was fully ported to unit tests 2017-08-11 21:23:55 +02:00
Marco Pivetta 15731c7bde #6613 #6614 #6616 ensuring that the collection is marked as non-dirty if all new items are contained in the initialized ones 2017-08-11 21:23:51 +02:00
Andreas Braun abb429a0c9 Add failing test for dirty flag 2017-08-11 21:23:47 +02:00
Marco Pivetta 61cb03bf30 #6613 #6614 #6616 removing repeated PersistentCollectionTest chunks of code 2017-08-11 21:23:40 +02:00
Marco Pivetta d6bcb5b1f8 #6613 #6614 #6616 initializing a dirty collection that has new items that are also coming from initialization data de-duplicates new and persisted items 2017-08-11 21:22:59 +02:00
Marco Pivetta bdae362777 #6613 #6614 #6616 moved integration test basics to a unit test that verifies basic dirty collection initialization semantics 2017-08-11 21:22:54 +02:00
Marco Pivetta 59c5574554 #6613 #6614 correcting broken test that isn't using objects against a PersistentCollection 2017-08-11 21:22:43 +02:00
Marco Pivetta 9545bf9d8c #6613 #6614 correcting broken test that isn't using objects against a PersistentCollection 2017-08-11 21:22:40 +02:00
Marco Pivetta 5521d1f325 #6613 #6614 ensuring that only newly added items that weren't loaded are restored in the dirty state of the collection 2017-08-11 21:22:34 +02:00
Marco Pivetta 49694dc335 #6613 #6614 after initialization, the collection should be dirty anyway 2017-08-11 21:21:43 +02:00
Marco Pivetta 3155d970d3 #6613 #6614 adding assertions about collection initialization and dirty status 2017-08-11 21:21:40 +02:00
Marco Pivetta 09189fc021 #6613 #6614 removing IDE-generated header 2017-08-11 21:21:36 +02:00
Marco Pivetta 5a0d3e5fb8 #6613 #6614 removing phone/user specifics, using ORM naming for associations 2017-08-11 21:21:27 +02:00
Marco Pivetta b9ba4e3207 #6613 #6614 correcting column mapping (was integer, should be string), segregating phone creation away 2017-08-11 21:21:24 +02:00
Marco Pivetta d7919678e5 #6613 #6614 remove superfluous mappings 2017-08-11 21:21:21 +02:00
Marco Pivetta 8b185eb822 #6613 #6614 rewrote test logic to be less magic-constant-dependent 2017-08-11 21:21:17 +02:00
Marco Pivetta 693a0546d3 #6613 #6614 CS - applying @group annotation to the test 2017-08-11 21:21:14 +02:00
Marco Pivetta 5c5c8fc487 #6613 #6614 removing dedicated DDC6613 model directory 2017-08-11 21:21:10 +02:00
Marco Pivetta 85dc707cc8 #6613 #6614 smashing entity definitions into the test 2017-08-11 21:21:03 +02:00
Marco Pivetta 64a1251b61 #6613 #6614 better test specification - removing useless assertions 2017-08-11 21:20:42 +02:00
Marco Pivetta 65ed6a2c2f #6613 #6614 simplifying entity definition - using auto-assigned string identifiers to reduce moving parts 2017-08-11 21:20:34 +02:00
Marco Pivetta d27a9fce7a Merge pull request #6580 from Tobion/patch-1
Allow DBAL 2.6 and common 2.8 to be installed
2017-07-25 05:02:26 +02:00
Tobias Schultze 11659f5cfe Allow common 2.8 to be installed 2017-07-24 16:38:01 +02:00
Tobias Schultze 68dad26482 Allow DBAL 2.6 to be installed
DBAL 2.6 is released but currently dependencies can't be resolved as ORM 2.5 does not allow DBAL 2.6 and ORM 2.6 is not relased yet.
2017-07-24 16:27:53 +02:00
Marco Pivetta b3ceef0fb6 Merge branch 'fix/#6550-correct-return-value-of-extra-lazy-removeElement-calls' into 2.5
Backport #6550 to 2.5
2017-07-22 09:27:30 +02:00
Andreas Braun 095b365146 Add test for removing element not in collection 2017-07-22 09:27:13 +02:00
Andreas Braun 7c1ebd99bc Fix return of removeElement on collections
Fixes #5745
2017-07-22 09:27:01 +02:00
Marco Pivetta c06f19db8d Merge branch 'fix/#1515-clean-hydrator-listeners-on-hydration-end-2.5' into 2.5
Close #1515

This is a backport of the original PR - the same patch should land in `master` too, after a cleanup
2017-06-24 03:23:19 +02:00
Emiel Nijpels 0be9be4e24 DDC-3146 remove event listener from event listener in abstract hydrator in cleanup function 2017-06-24 03:23:01 +02:00
Luís Cobucci b2bf5ee92e Leave PHP 7.1 and nightly to master 2017-06-22 07:57:54 +02:00
Luís Cobucci 698bd813a2 Remove HHVM from build 2017-06-22 07:46:45 +02:00
Jáchym Toušek b2ac8fdfd7 Fix CountOutputWalker for queries with GROUP BY 2017-06-22 07:15:35 +02:00
Marco Pivetta 9c2b54b748 Adding classes required by the SchemaToolTest that exist in 'master', but not in '2.5' 2017-06-21 07:27:41 +02:00
Marco Pivetta 910784213f Corrected duplicate import statements due to cherry picking 2017-06-21 06:49:45 +02:00
Marco Pivetta 1d1de7de80 Merge branch 'fix/#5798-undefined-schema-tool-index-2.5' into 2.5
Close #5798
2017-06-21 06:32:00 +02:00
Sergey Fedotov 741da6eed7 Fix undefined index for discriminator column in SchemaTool 2017-06-21 06:31:23 +02:00
Marco Pivetta ad5397b581 Merge branch 'fix/#5715-fix-metadata-filtering-in-cli-tools-2.5' into 2.5
Close #5715
2017-06-21 06:15:42 +02:00
Guilliam Xavier 57bb46ca9d Add regex tests for MetadataFilter (PR #507) 2017-06-21 06:15:25 +02:00
Guilliam Xavier 0416d5e036 Add more basic tests for MetadataFilter 2017-06-21 06:15:14 +02:00
Guilliam Xavier a14432117a Fix MetadataFilter not testing filters after first 2017-06-21 06:15:01 +02:00
Guilliam Xavier 824f62d3bb Add failing test for #5715 (unit test for MetadataFilter) 2017-06-21 06:14:48 +02:00
Marco Pivetta c0f0fe060f Merge branch 'fix/#1541-minor-docblock-correction-in-resultset-mapping-builder' into 2.5
Backport #1541 to 2.5
2017-05-20 16:45:59 +02:00
aleeeftw caffbe04a2 Minor docblock correction
The documentation for the method ‘addJoinedEntityFromClassMetadata’ is
wrong. As we can see currently says you need to pass an object and that
is wrong. The $relation variable is passed to ‘addJoinedEntityResult’
which is using it as a ‘string’.
2017-05-20 16:45:25 +02:00
Marco Pivetta d2c805b071 Correcting PHP 5.4 compliance by removing ::class usage (moving to real constants) 2017-05-02 09:33:48 +02:00
Marco Pivetta 04fc7a9a1c Merge branch 'fix/#6367-#6362-inheritance-alias-hydration' into 2.5
Close #6367
Close #6362
2017-05-02 09:26:54 +02:00
Timothy Clissold 149b8f4e09 Fix inheritance join alias 2017-05-02 09:26:44 +02:00
Marco Pivetta 48e8c02cb8 Merge pull request #6381 from ElisDN/ElisDN-phpdoc
Fixed PHPDoc
2017-04-03 09:04:13 +02:00
Елисеев Дмитрий e218866a69 Fixed PHPDoc 2017-04-02 20:29:46 +03:00
47 changed files with 1554 additions and 175 deletions
+6 -13
View File
@@ -5,8 +5,6 @@ php:
- 5.5
- 5.6
- 7.0
- hhvm
- hhvm-nightly
env:
- DB=mysql
@@ -15,7 +13,7 @@ env:
before_script:
- if [[ $TRAVIS_PHP_VERSION = '5.6' && $DB = 'sqlite' ]]; then PHPUNIT_FLAGS="--coverage-clover ./build/logs/clover.xml"; else PHPUNIT_FLAGS=""; fi
- if [[ $TRAVIS_PHP_VERSION != '5.6' && $TRAVIS_PHP_VERSION != 'hhvm' && $TRAVIS_PHP_VERSION != 'hhvm-nightly' && $TRAVIS_PHP_VERSION != '7.0' ]]; then phpenv config-rm xdebug.ini; fi
- if [[ $PHPUNIT_FLAGS == "" ]]; then phpenv config-rm xdebug.ini; fi
- composer self-update
- composer install --prefer-source --dev
@@ -24,15 +22,10 @@ script:
- ENABLE_SECOND_LEVEL_CACHE=1 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml --exclude-group performance,non-cacheable,locking_functional
matrix:
exclude:
- php: hhvm
env: DB=pgsql # driver currently unsupported by HHVM
- php: hhvm
env: DB=mysqli # driver currently unsupported by HHVM
- php: hhvm-nightly
env: DB=pgsql # driver currently unsupported by HHVM
- php: hhvm-nightly
env: DB=mysqli # driver currently unsupported by HHVM
fast_finish: true
allow_failures:
- php: 7.0
- php: hhvm-nightly # hhvm-nightly currently chokes on composer installation
cache:
directories:
- $HOME/.composer/cache
+5 -5
View File
@@ -16,14 +16,14 @@
"php": ">=5.4",
"ext-pdo": "*",
"doctrine/collections": "~1.2",
"doctrine/dbal": ">=2.5-dev,<2.6-dev",
"doctrine/instantiator": "~1.0.1",
"doctrine/common": ">=2.5-dev,<2.8-dev",
"doctrine/dbal": ">=2.5-dev,<2.7-dev",
"doctrine/instantiator": "^1.0.1",
"doctrine/common": ">=2.5-dev,<2.9-dev",
"doctrine/cache": "~1.4",
"symfony/console": "~2.5|~3.0"
"symfony/console": "~2.5|~3.0|~4.0"
},
"require-dev": {
"symfony/yaml": "~2.3|~3.0",
"symfony/yaml": "~2.3|~3.0|~4.0",
"phpunit/phpunit": "~4.0"
},
"suggest": {
+8 -15
View File
@@ -325,14 +325,14 @@ abstract class AbstractQuery
public function getParameter($key)
{
$filteredParameters = $this->parameters->filter(
function ($parameter) use ($key)
{
// Must not be identical because of string to integer conversion
return ($key == $parameter->getName());
function (Query\Parameter $parameter) use ($key) {
$parameterName = $parameter->getName();
return $key === $parameterName || (string) $key === (string) $parameterName;
}
);
return count($filteredParameters) ? $filteredParameters->first() : null;
return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null;
}
/**
@@ -373,17 +373,10 @@ abstract class AbstractQuery
*/
public function setParameter($key, $value, $type = null)
{
$filteredParameters = $this->parameters->filter(
function ($parameter) use ($key)
{
// Must not be identical because of string to integer conversion
return ($key == $parameter->getName());
}
);
$existingParameter = $this->getParameter($key);
if (count($filteredParameters)) {
$parameter = $filteredParameters->first();
$parameter->setValue($value, $type);
if ($existingParameter !== null) {
$existingParameter->setValue($value, $type);
return $this;
}
@@ -30,7 +30,7 @@ use Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs as BaseLoadClas
* Note: method annotations are used instead of method overrides (due to BC policy)
*
* @method __construct(\Doctrine\ORM\Mapping\ClassMetadata $classMetadata, \Doctrine\ORM\EntityManager $objectManager)
* @method \Doctrine\ORM\EntityManager getClassMetadata()
* @method \Doctrine\ORM\Mapping\ClassMetadata getClassMetadata()
*/
class LoadClassMetadataEventArgs extends BaseLoadClassMetadataEventArgs
{
+6 -3
View File
@@ -76,7 +76,8 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
$conn = $em->getConnection();
$sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName);
$this->_nextValue = (int)$conn->fetchColumn($sql);
// Using `query` to force usage of the master server in MasterSlaveConnection
$this->_nextValue = (int) $conn->query($sql)->fetchColumn();
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
}
@@ -108,10 +109,12 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
*/
public function serialize()
{
return serialize(array(
return serialize(
[
'allocationSize' => $this->_allocationSize,
'sequenceName' => $this->_sequenceName
));
]
);
}
/**
@@ -142,6 +142,9 @@ abstract class AbstractHydrator
$this->_rsm = $resultSetMapping;
$this->_hints = $hints;
$evm = $this->_em->getEventManager();
$evm->addEventListener(array(Events::onClear), $this);
$this->prepare();
$result = $this->hydrateAllData();
@@ -210,6 +213,9 @@ abstract class AbstractHydrator
$this->_rsm = null;
$this->_cache = array();
$this->_metadataCache = array();
$evm = $this->_em->getEventManager();
$evm->removeEventListener(array(Events::onClear), $this);
}
/**
@@ -360,8 +360,8 @@ class ObjectHydrator extends AbstractHydrator
// Get a reference to the parent object to which the joined element belongs.
if ($this->_rsm->isMixed && isset($this->rootAliases[$parentAlias])) {
$first = reset($this->resultPointers);
$parentObject = $first[key($first)];
$objectClass = $this->resultPointers[$parentAlias];
$parentObject = $objectClass[key($objectClass)];
} else if (isset($this->resultPointers[$parentAlias])) {
$parentObject = $this->resultPointers[$parentAlias];
} else {
@@ -2949,7 +2949,7 @@ class ClassMetadataInfo implements ClassMetadata
*/
public function setSequenceGeneratorDefinition(array $definition)
{
if ( ! isset($definition['sequenceName'])) {
if ( ! isset($definition['sequenceName']) || trim($definition['sequenceName']) === '') {
throw MappingException::missingSequenceName($this->name);
}
@@ -2958,6 +2958,14 @@ class ClassMetadataInfo implements ClassMetadata
$definition['quoted'] = true;
}
if ( ! isset($definition['allocationSize']) || trim($definition['allocationSize']) === '') {
$definition['allocationSize'] = '1';
}
if ( ! isset($definition['initialValue']) || trim($definition['initialValue']) === '') {
$definition['initialValue'] = '1';
}
$this->sequenceGeneratorDefinition = $definition;
}
@@ -811,7 +811,8 @@ class XmlDriver extends FileDriver
protected function loadMappingFile($file)
{
$result = array();
$xmlElement = simplexml_load_file($file);
// Note: we do not use `simplexml_load_file()` because of https://bugs.php.net/bug.php?id=62577
$xmlElement = simplexml_load_string(file_get_contents($file));
if (isset($xmlElement->entity)) {
foreach ($xmlElement->entity as $entityElement) {
+28 -13
View File
@@ -19,7 +19,6 @@
namespace Doctrine\ORM;
use Closure;
use Doctrine\Common\Collections\AbstractLazyCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
@@ -375,11 +374,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
$persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association);
if ($persister->removeElement($this, $element)) {
return $element;
}
return null;
return $persister->removeElement($this, $element);
}
$removed = parent::removeElement($element);
@@ -689,21 +684,41 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
protected function doInitialize()
{
// Has NEW objects added through add(). Remember them.
$newObjects = array();
$newlyAddedDirtyObjects = array();
if ($this->isDirty) {
$newObjects = $this->collection->toArray();
$newlyAddedDirtyObjects = $this->collection->toArray();
}
$this->collection->clear();
$this->em->getUnitOfWork()->loadCollection($this);
$this->takeSnapshot();
// Reattach NEW objects added through add(), if any.
if ($newObjects) {
foreach ($newObjects as $obj) {
$this->collection->add($obj);
}
if ($newlyAddedDirtyObjects) {
$this->restoreNewObjectsInDirtyCollection($newlyAddedDirtyObjects);
}
}
/**
* @param object[] $newObjects
*
* @return void
*
* Note: the only reason why this entire looping/complexity is performed via `spl_object_hash`
* is because we want to prevent using `array_udiff()`, which is likely to cause very
* high overhead (complexity of O(n^2)). `array_diff_key()` performs the operation in
* core, which is faster than using a callback for comparisons
*/
private function restoreNewObjectsInDirtyCollection(array $newObjects)
{
$loadedObjects = $this->collection->toArray();
$newObjectsByOid = \array_combine(\array_map('spl_object_hash', $newObjects), $newObjects);
$loadedObjectsByOid = \array_combine(\array_map('spl_object_hash', $loadedObjects), $loadedObjects);
$newObjectsThatWereNotLoaded = \array_diff_key($newObjectsByOid, $loadedObjectsByOid);
if ($newObjectsThatWereNotLoaded) {
// Reattach NEW objects added through add(), if any.
\array_walk($newObjectsThatWereNotLoaded, [$this->collection, 'add']);
$this->isDirty = true;
}
@@ -239,9 +239,10 @@ class ManyToManyPersister extends AbstractCollectionPersister
$parameters = $this->expandCriteriaParameters($criteria);
foreach ($parameters as $parameter) {
list($name, $value) = $parameter;
$whereClauses[] = sprintf('te.%s = ?', $name);
$params[] = $value;
list($name, $value, $operator) = $parameter;
$whereClauses[] = sprintf('te.%s %s ?', $name, $operator);
$params[] = $value;
}
$mapping = $collection->getMapping();
@@ -820,7 +820,7 @@ class BasicEntityPersister implements EntityPersister
? $this->expandCriteriaParameters($criteria)
: $this->expandParameters($criteria);
return $this->conn->executeQuery($sql, $params, $types)->fetchColumn();
return (int) $this->conn->executeQuery($sql, $params, $types)->fetchColumn();
}
/**
@@ -61,7 +61,7 @@ class SqlValueVisitor extends ExpressionVisitor
}
$this->values[] = $value;
$this->types[] = array($field, $value);
$this->types[] = array($field, $value, $operator);
}
/**
+3 -1
View File
@@ -91,7 +91,9 @@ class ProxyFactory extends AbstractProxyFactory
protected function skipClass(ClassMetadata $metadata)
{
/* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
return $metadata->isMappedSuperclass || $metadata->getReflectionClass()->isAbstract();
return $metadata->isMappedSuperclass
|| $metadata->isEmbeddedClass
|| $metadata->getReflectionClass()->isAbstract();
}
/**
@@ -110,7 +110,7 @@ class ResultSetMappingBuilder extends ResultSetMapping
* @param string $class The class name of the joined entity.
* @param string $alias The unique alias to use for the joined entity.
* @param string $parentAlias The alias of the entity result that is the parent of this joined result.
* @param object $relation The association field that connects the parent entity result
* @param string $relation The association field that connects the parent entity result
* with the joined entity result.
* @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName).
* @param int|null $renameMode One of the COLUMN_RENAMING_* constants or array for BC reasons (CUSTOM).
+23 -5
View File
@@ -870,6 +870,19 @@ class SqlWalker implements TreeWalker
* @return string
*/
public function walkRangeVariableDeclaration($rangeVariableDeclaration)
{
return $this->generateRangeVariableDeclarationSQL($rangeVariableDeclaration, false);
}
/**
* Generate appropriate SQL for RangeVariableDeclaration AST node
*
* @param AST\RangeVariableDeclaration $rangeVariableDeclaration
* @param bool $buildNestedJoins
*
* @return string
*/
private function generateRangeVariableDeclarationSQL($rangeVariableDeclaration, $buildNestedJoins)
{
$class = $this->em->getClassMetadata($rangeVariableDeclaration->abstractSchemaName);
$dqlAlias = $rangeVariableDeclaration->aliasIdentificationVariable;
@@ -885,7 +898,11 @@ class SqlWalker implements TreeWalker
);
if ($class->isInheritanceTypeJoined()) {
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
if ($buildNestedJoins) {
$sql = '(' . $sql . $this->_generateClassTableInheritanceJoins($class, $dqlAlias) . ')';
} else {
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
}
}
return $sql;
@@ -1121,16 +1138,17 @@ class SqlWalker implements TreeWalker
: ' INNER JOIN ';
switch (true) {
case ($joinDeclaration instanceof \Doctrine\ORM\Query\AST\RangeVariableDeclaration):
case ($joinDeclaration instanceof AST\RangeVariableDeclaration):
$class = $this->em->getClassMetadata($joinDeclaration->abstractSchemaName);
$dqlAlias = $joinDeclaration->aliasIdentificationVariable;
$tableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
$condition = '(' . $this->walkConditionalExpression($join->conditionalExpression) . ')';
$condExprConjunction = ($class->isInheritanceTypeJoined() && $joinType != AST\Join::JOIN_TYPE_LEFT && $joinType != AST\Join::JOIN_TYPE_LEFTOUTER)
$isUnconditionalJoin = empty($condition);
$condExprConjunction = ($class->isInheritanceTypeJoined() && $joinType != AST\Join::JOIN_TYPE_LEFT && $joinType != AST\Join::JOIN_TYPE_LEFTOUTER && $isUnconditionalJoin)
? ' AND '
: ' ON ';
$sql .= $this->walkRangeVariableDeclaration($joinDeclaration);
$sql .= $this->generateRangeVariableDeclarationSQL($joinDeclaration, !$isUnconditionalJoin);
$conditions = array($condition);
@@ -1151,7 +1169,7 @@ class SqlWalker implements TreeWalker
$sql .= $condExprConjunction . implode(' AND ', $conditions);
break;
case ($joinDeclaration instanceof \Doctrine\ORM\Query\AST\JoinAssociationDeclaration):
case ($joinDeclaration instanceof AST\JoinAssociationDeclaration):
$sql .= $this->walkJoinAssociationDeclaration($joinDeclaration, $joinType, $join->conditionalExpression);
break;
}
+9 -18
View File
@@ -529,24 +529,15 @@ class QueryBuilder
*/
public function setParameter($key, $value, $type = null)
{
$filteredParameters = $this->parameters->filter(
function ($parameter) use ($key)
{
// Must not be identical because of string to integer conversion
return ($key == $parameter->getName());
}
);
$existingParameter = $this->getParameter($key);
if (count($filteredParameters)) {
$parameter = $filteredParameters->first();
$parameter->setValue($value, $type);
if ($existingParameter !== null) {
$existingParameter->setValue($value, $type);
return $this;
}
$parameter = new Query\Parameter($key, $value, $type);
$this->parameters->add($parameter);
$this->parameters->add(new Query\Parameter($key, $value, $type));
return $this;
}
@@ -609,14 +600,14 @@ class QueryBuilder
public function getParameter($key)
{
$filteredParameters = $this->parameters->filter(
function ($parameter) use ($key)
{
// Must not be identical because of string to integer conversion
return ($key == $parameter->getName());
function (Query\Parameter $parameter) use ($key) {
$parameterName = $parameter->getName();
return $key === $parameterName || (string) $key === (string) $parameterName;
}
);
return count($filteredParameters) ? $filteredParameters->first() : null;
return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null;
}
/**
@@ -84,10 +84,6 @@ class MetadataFilter extends \FilterIterator implements \Countable
);
}
if ($pregResult === 0) {
return false;
}
if ($pregResult) {
return true;
}
@@ -85,6 +85,14 @@ class CountOutputWalker extends SqlWalker
$sql = parent::walkSelectStatement($AST);
if ($AST->groupByClause) {
return sprintf(
'SELECT %s AS dctrn_count FROM (%s) dctrn_table',
$this->platform->getCountExpression('*'),
$sql
);
}
// 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
// would probably require issuing multiple queries or doing a UNION SELECT
+1 -1
View File
@@ -345,7 +345,7 @@ class SchemaTool
$discrColumn = $class->discriminatorColumn;
if ( ! isset($discrColumn['type']) ||
(strtolower($discrColumn['type']) == 'string' && $discrColumn['length'] === null)
(strtolower($discrColumn['type']) == 'string' && ! isset($discrColumn['length']))
) {
$discrColumn['type'] = 'string';
$discrColumn['length'] = 255;
+75 -27
View File
@@ -15,7 +15,7 @@
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
*/
namespace Doctrine\ORM\Tools;
@@ -122,32 +122,7 @@ class Setup
public static function createConfiguration($isDevMode = false, $proxyDir = null, Cache $cache = null)
{
$proxyDir = $proxyDir ?: sys_get_temp_dir();
if ($isDevMode === false && $cache === null) {
if (extension_loaded('apc')) {
$cache = new \Doctrine\Common\Cache\ApcCache();
} elseif (extension_loaded('xcache')) {
$cache = new \Doctrine\Common\Cache\XcacheCache();
} elseif (extension_loaded('memcache')) {
$memcache = new \Memcache();
$memcache->connect('127.0.0.1');
$cache = new \Doctrine\Common\Cache\MemcacheCache();
$cache->setMemcache($memcache);
} elseif (extension_loaded('redis')) {
$redis = new \Redis();
$redis->connect('127.0.0.1');
$cache = new \Doctrine\Common\Cache\RedisCache();
$cache->setRedis($redis);
} else {
$cache = new ArrayCache();
}
} elseif ($cache === null) {
$cache = new ArrayCache();
}
if ($cache instanceof CacheProvider) {
$cache->setNamespace("dc2_" . md5($proxyDir) . "_"); // to avoid collisions
}
$cache = self::createCacheConfiguration($isDevMode, $proxyDir, $cache);
$config = new Configuration();
$config->setMetadataCacheImpl($cache);
@@ -159,4 +134,77 @@ class Setup
return $config;
}
/**
* @param bool $isDevMode
* @param string $proxyDir
* @param Cache|null $cache
*
* @return Cache
*/
private static function createCacheConfiguration($isDevMode, $proxyDir, Cache $cache = null)
{
$cache = self::createCacheInstance($isDevMode, $cache);
if ( ! $cache instanceof CacheProvider) {
return $cache;
}
$namespace = $cache->getNamespace();
if ($namespace !== '') {
$namespace .= ':';
}
$cache->setNamespace($namespace . 'dc2_' . md5($proxyDir) . '_'); // to avoid collisions
return $cache;
}
/**
* @param bool $isDevMode
* @param Cache|null $cache
*
* @return Cache
*/
private static function createCacheInstance($isDevMode, Cache $cache = null)
{
if ($cache !== null) {
return $cache;
}
if ($isDevMode === true) {
return new ArrayCache();
}
if (extension_loaded('apc')) {
return new \Doctrine\Common\Cache\ApcCache();
}
if (extension_loaded('xcache')) {
return new \Doctrine\Common\Cache\XcacheCache();
}
if (extension_loaded('memcache')) {
$memcache = new \Memcache();
$memcache->connect('127.0.0.1');
$cache = new \Doctrine\Common\Cache\MemcacheCache();
$cache->setMemcache($memcache);
return $cache;
}
if (extension_loaded('redis')) {
$redis = new \Redis();
$redis->connect('127.0.0.1');
$cache = new \Doctrine\Common\Cache\RedisCache();
$cache->setRedis($redis);
return $cache;
}
return new ArrayCache();
}
}
+2 -2
View File
@@ -22,7 +22,7 @@ namespace Doctrine\ORM;
/**
* Class to store and retrieve the version of Doctrine
*
*
*
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
@@ -36,7 +36,7 @@ class Version
/**
* Current Doctrine Version
*/
const VERSION = '2.5.5-DEV';
const VERSION = '2.5.13';
/**
* Compares a Doctrine version with the current one.
+51 -8
View File
@@ -2,16 +2,29 @@
namespace Doctrine\Tests\Mocks;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Statement;
/**
* Mock class for Connection.
*/
class ConnectionMock extends \Doctrine\DBAL\Connection
class ConnectionMock extends Connection
{
/**
* @var mixed
*/
private $_fetchOneResult;
/**
* @var \Exception|null
*/
private $_fetchOneException;
/**
* @var Statement|null
*/
private $_queryResult;
/**
* @var DatabasePlatformMock
*/
@@ -25,12 +38,12 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
/**
* @var array
*/
private $_inserts = array();
private $_inserts = [];
/**
* @var array
*/
private $_executeUpdates = array();
private $_executeUpdates = [];
/**
* @param array $params
@@ -59,7 +72,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
/**
* {@inheritdoc}
*/
public function insert($tableName, array $data, array $types = array())
public function insert($tableName, array $data, array $types = [])
{
$this->_inserts[$tableName][] = $data;
}
@@ -67,9 +80,9 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
/**
* {@inheritdoc}
*/
public function executeUpdate($query, array $params = array(), array $types = array())
public function executeUpdate($query, array $params = [], array $types = [])
{
$this->_executeUpdates[] = array('query' => $query, 'params' => $params, 'types' => $types);
$this->_executeUpdates[] = ['query' => $query, 'params' => $params, 'types' => $types];
}
/**
@@ -83,11 +96,23 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
/**
* {@inheritdoc}
*/
public function fetchColumn($statement, array $params = array(), $colnum = 0, array $types = array())
public function fetchColumn($statement, array $params = [], $colnum = 0, array $types = [])
{
if (null !== $this->_fetchOneException) {
throw $this->_fetchOneException;
}
return $this->_fetchOneResult;
}
/**
* {@inheritdoc}
*/
public function query()
{
return $this->_queryResult;
}
/**
* {@inheritdoc}
*/
@@ -111,6 +136,16 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
$this->_fetchOneResult = $fetchOneResult;
}
/**
* @param \Exception|null $exception
*
* @return void
*/
public function setFetchOneException(\Exception $exception = null)
{
$this->_fetchOneException = $exception;
}
/**
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
*
@@ -131,6 +166,14 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
$this->_lastInsertId = $id;
}
/**
* @param Statement $result
*/
public function setQueryResult(Statement $result)
{
$this->_queryResult = $result;
}
/**
* @return array
*/
@@ -152,7 +195,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
*/
public function reset()
{
$this->_inserts = array();
$this->_inserts = [];
$this->_lastInsertId = 0;
}
}
@@ -0,0 +1,65 @@
<?php
namespace Doctrine\Tests\Mocks;
/**
* Simple statement mock that returns result based on array.
* Doesn't support fetch modes
*/
class StatementArrayMock extends StatementMock
{
/**
* @var array
*/
private $_result;
public function __construct($result)
{
$this->_result = $result;
}
public function getIterator()
{
return new \ArrayIterator($this->_result);
}
public function columnCount()
{
$row = reset($this->_result);
if ($row) {
return count($row);
} else {
return 0;
}
}
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
return $this->_result;
}
public function fetch($fetchMode = null, $cursorOrientation = \PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{
$current = current($this->_result);
next($this->_result);
return $current;
}
public function fetchColumn($columnIndex = 0)
{
$current = current($this->_result);
if ($current) {
next($this->_result);
return reset($current);
} else {
return false;
}
}
public function rowCount()
{
return count($this->_result);
}
}
@@ -27,7 +27,7 @@ class DefaultRegionTest extends AbstractRegionTest
public function testSharedRegion()
{
if ( ! extension_loaded('apc') || false === @apc_cache_info()) {
if ( ! extension_loaded('apc') || ! is_array(@apc_cache_info("user"))) {
$this->markTestSkipped('The ' . __CLASS__ .' requires the use of APC');
}
@@ -97,4 +97,4 @@ class DefaultRegionTest extends AbstractRegionTest
$this->assertEquals($value1, $actual[0]);
$this->assertEquals($value2, $actual[1]);
}
}
}
@@ -28,7 +28,7 @@ class NonStrictReadWriteCachedEntityPersisterTest extends AbstractEntityPersiste
{
$entity = new Country("Foo");
$persister = $this->createPersisterDefault();
$property = new \ReflectionProperty('Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister', 'queuedCache');
$property = new \ReflectionProperty($persister, 'queuedCache');
$property->setAccessible(true);
@@ -50,7 +50,7 @@ class NonStrictReadWriteCachedEntityPersisterTest extends AbstractEntityPersiste
$persister = $this->createPersisterDefault();
$key = new EntityCacheKey(Country::CLASSNAME, array('id'=>1));
$entry = new EntityCacheEntry(Country::CLASSNAME, array('id'=>1, 'name'=>'Foo'));
$property = new \ReflectionProperty('Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister', 'queuedCache');
$property = new \ReflectionProperty($persister, 'queuedCache');
$property->setAccessible(true);
@@ -87,7 +87,7 @@ class NonStrictReadWriteCachedEntityPersisterTest extends AbstractEntityPersiste
$persister = $this->createPersisterDefault();
$key = new EntityCacheKey(Country::CLASSNAME, array('id'=>1));
$entry = new EntityCacheEntry(Country::CLASSNAME, array('id'=>1, 'name'=>'Foo'));
$property = new \ReflectionProperty('Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister', 'queuedCache');
$property = new \ReflectionProperty($persister, 'queuedCache');
$property->setAccessible(true);
@@ -115,7 +115,7 @@ class NonStrictReadWriteCachedEntityPersisterTest extends AbstractEntityPersiste
$entity = new Country("Foo");
$persister = $this->createPersisterDefault();
$key = new EntityCacheKey(Country::CLASSNAME, array('id'=>1));
$property = new \ReflectionProperty('Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister', 'queuedCache');
$property = new \ReflectionProperty($persister, 'queuedCache');
$property->setAccessible(true);
@@ -636,11 +636,13 @@ class ExtraLazyCollectionTest extends OrmFunctionalTestCase
$group = $this->_em->find('Doctrine\Tests\Models\CMS\CmsGroup', $this->groupId);
$queryCount = $this->getCurrentQueryCount();
$user->groups->removeElement($group);
$this->assertTrue($user->groups->removeElement($group));
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Removing a persisted entity should cause one query to be executed.");
$this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
$this->assertFalse($user->groups->removeElement($group), "Removing an already removed element returns false");
// Test Many to Many removal with Entity state as new
$group = new \Doctrine\Tests\Models\CMS\CmsGroup();
$group->name = "A New group!";
@@ -129,6 +129,7 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
->will($this->returnValue( 10 ));
$parserResultMock = $this->getMock('Doctrine\ORM\Query\ParserResult');
$parserResultMock->method('getParameterMappings')->willReturn(array());
$parserResultMock->expects($this->once())
->method('getSqlExecutor')
->will($this->returnValue($sqlExecMock));
@@ -0,0 +1,65 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
/**
* @group DDC-3146
* @author Emiel Nijpels <emiel@silverstreet.com>
*/
class DDC3146Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
/**
* Verify that the number of added events to the event listener from the abstract hydrator class is equal to the number of removed events
*/
public function testEventListeners()
{
// Create mock connection to be returned from the entity manager interface
$mockConnection = $this->getMockBuilder('Doctrine\DBAL\Connection')->disableOriginalConstructor()->getMock();
$mockEntityManagerInterface = $this->getMockBuilder('Doctrine\ORM\EntityManagerInterface')->disableOriginalConstructor()->getMock();
$mockEntityManagerInterface->expects($this->any())->method('getConnection')->will($this->returnValue($mockConnection));
// Create mock event manager to be returned from the entity manager interface
$mockEventManager = $this->getMockBuilder('Doctrine\Common\EventManager')->disableOriginalConstructor()->getMock();
$mockEntityManagerInterface->expects($this->any())->method('getEventManager')->will($this->returnValue($mockEventManager));
// Create mock statement and result mapping
$mockStatement = $this->getMockBuilder('Doctrine\DBAL\Driver\Statement')->disableOriginalConstructor()->getMock();
$mockStatement->expects($this->once())->method('fetch')->will($this->returnValue(false));
$mockResultMapping = $this->getMockBuilder('Doctrine\ORM\Query\ResultSetMapping')->disableOriginalConstructor()->getMock();
// Create mock abstract hydrator
$mockAbstractHydrator = $this->getMockBuilder('Doctrine\ORM\Internal\Hydration\AbstractHydrator')
->setConstructorArgs(array($mockEntityManagerInterface))
->setMethods(array('hydrateAllData'))
->getMock();
// Increase counter every time the event listener is added and decrease the counter every time the event listener is removed
$eventCounter = 0;
$mockEventManager->expects($this->any())
->method('addEventListener')
->will(
$this->returnCallback(
function () use (&$eventCounter) {
$eventCounter++;
}
)
);
$mockEventManager->expects($this->any())
->method('removeEventListener')
->will(
$this->returnCallback(
function () use (&$eventCounter) {
$eventCounter--;
}
)
);
// Create iterable result
$iterableResult = $mockAbstractHydrator->iterate($mockStatement, $mockResultMapping, array());
$iterableResult->next();
// Number of added events listeners should be equal or less than the number of removed events
$this->assertLessThanOrEqual(0, $eventCounter, 'More events added to the event listener than removed; this can create a memory leak when references are not cleaned up');
}
}
@@ -0,0 +1,152 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\OrmFunctionalTestCase;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Tests\Mocks\HydratorMockStatement;
final class GH6362Test extends OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(
[
$this->_em->getClassMetadata(GH6362Start::CLASSNAME),
$this->_em->getClassMetadata(GH6362Base::CLASSNAME),
$this->_em->getClassMetadata(GH6362Child::CLASSNAME),
$this->_em->getClassMetadata(GH6362Join::CLASSNAME),
]
);
}
/**
* @group 6362
*
* SELECT a as base, b, c, d
* FROM Start a
* LEFT JOIN a.bases b
* LEFT JOIN Child c WITH b.id = c.id
* LEFT JOIN c.joins d
*/
public function testInheritanceJoinAlias()
{
$rsm = new ResultSetMapping;
$rsm->addEntityResult(GH6362Start::CLASSNAME, 'a', 'base');
$rsm->addJoinedEntityResult(GH6362Base::CLASSNAME, 'b', 'a', 'bases');
$rsm->addEntityResult(GH6362Child::CLASSNAME, 'c');
$rsm->addJoinedEntityResult(GH6362Join::CLASSNAME, 'd', 'c', 'joins');
$rsm->addFieldResult('a', 'id_0', 'id');
$rsm->addFieldResult('b', 'id_1', 'id');
$rsm->addFieldResult('c', 'id_2', 'id');
$rsm->addFieldResult('d', 'id_3', 'id');
$rsm->addMetaResult('a', 'bases_id_4', 'bases_id', false, 'integer');
$rsm->addMetaResult('b', 'type_5', 'type');
$rsm->addMetaResult('c', 'type_6', 'type');
$rsm->addMetaResult('d', 'child_id_7', 'child_id', false, 'integer');
$rsm->setDiscriminatorColumn('b', 'type_5');
$rsm->setDiscriminatorColumn('c', 'type_6');
$resultSet = [
[
'id_0' => '1',
'id_1' => '1',
'id_2' => '1',
'id_3' => '1',
'bases_id_4' => '1',
'type_5' => 'child',
'type_6' => 'child',
'child_id_7' => '1',
],
];
$stmt = new HydratorMockStatement($resultSet);
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
$result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]);
$this->assertInstanceOf(GH6362Start::CLASSNAME, $result[0]['base']);
$this->assertInstanceOf(GH6362Child::CLASSNAME, $result[1][0]);
}
}
/**
* @Entity
*/
class GH6362Start
{
const CLASSNAME = __CLASS__;
/**
* @Column(type="integer")
* @Id
* @GeneratedValue
*/
protected $id;
/**
* @ManyToOne(targetEntity="GH6362Base", inversedBy="starts")
*/
private $bases;
}
/**
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap({"child" = "GH6362Child"})
* @Entity
*/
abstract class GH6362Base
{
const CLASSNAME = __CLASS__;
/**
* @Column(type="integer")
* @Id
* @GeneratedValue
*/
protected $id;
/**
* @OneToMany(targetEntity="GH6362Start", mappedBy="bases")
*/
private $starts;
}
/**
* @Entity
*/
class GH6362Child extends GH6362Base
{
const CLASSNAME = __CLASS__;
/**
* @OneToMany(targetEntity="GH6362Join", mappedBy="child")
*/
private $joins;
}
/**
* @Entity
*/
class GH6362Join
{
const CLASSNAME = __CLASS__;
/**
* @Column(type="integer")
* @Id
* @GeneratedValue
*/
private $id;
/**
* @ManyToOne(targetEntity="GH6362Child", inversedBy="joins")
*/
private $child;
}
@@ -0,0 +1,81 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @group GH-6464
*/
class GH6464Test extends OrmFunctionalTestCase
{
/**
* {@inheritDoc}
*/
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema([
$this->_em->getClassMetadata(GH6464Post::CLASS_NAME),
$this->_em->getClassMetadata(GH6464User::CLASS_NAME),
$this->_em->getClassMetadata(GH6464Author::CLASS_NAME),
]);
}
/**
* Verifies that SqlWalker generates valid SQL for an INNER JOIN to CTI table
*
* SqlWalker needs to generate nested INNER JOIN statements, otherwise there would be INNER JOIN
* statements without an ON clause, which are valid on e.g. MySQL but rejected by PostgreSQL.
*/
public function testIssue()
{
$query = $this->_em->createQueryBuilder()
->select('p')
->from(GH6464Post::CLASS_NAME, 'p')
->innerJoin(GH6464Author::CLASS_NAME, 'a', 'WITH', 'p.authorId = a.id')
->getQuery();
$this->assertNotRegExp(
'/INNER JOIN \w+ \w+ INNER JOIN/',
$query->getSQL(),
'As of GH-6464, every INNER JOIN should have an ON clause, which is missing here'
);
// Query shouldn't yield a result, yet it shouldn't crash (anymore)
$this->assertEquals([], $query->getResult());
}
}
/** @Entity */
class GH6464Post
{
const CLASS_NAME = __CLASS__;
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @Column(type="integer") */
public $authorId;
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"author" = "GH6464Author"})
*/
abstract class GH6464User
{
const CLASS_NAME = __CLASS__;
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
}
/** @Entity */
class GH6464Author extends GH6464User
{
const CLASS_NAME = __CLASS__;
}
@@ -0,0 +1,29 @@
<?php
namespace Doctrine\Test\ORM\Functional\Ticket;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\Tests\OrmFunctionalTestCase;
final class GH6682Test extends OrmFunctionalTestCase
{
/**
* @group 6682
*/
public function testIssue()
{
$parsedDefinition = [
'sequenceName' => 'test_sequence',
'allocationSize' => '',
'initialValue' => '',
];
$classMetadataInfo = new ClassMetadataInfo('test_entity');
$classMetadataInfo->setSequenceGeneratorDefinition($parsedDefinition);
self::assertSame(
['sequenceName' => 'test_sequence', 'allocationSize' => '1', 'initialValue' => '1'],
$classMetadataInfo->sequenceGeneratorDefinition
);
}
}
@@ -0,0 +1,55 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @group 6699
*/
final class GH6699Test extends OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testMixedParametersWithZeroNumber()
{
$query = $this->_em->createQueryBuilder()
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->andWhere('u.username = :username')
->andWhere('u.id = ?0')
->getQuery();
$query->setParameter('username', 'bar');
$query->setParameter(0, 0);
$query->execute();
self::assertCount(2, $query->getParameters());
self::assertSame(0, $query->getParameter(0)->getValue());
self::assertSame('bar', $query->getParameter('username')->getValue());
}
public function testMixedParametersWithZeroNumberOnQueryBuilder()
{
$query = $this->_em->createQueryBuilder()
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->andWhere('u.username = :username')
->andWhere('u.id = ?0')
->setParameter('username', 'bar')
->setParameter(0, 0)
->getQuery();
$query->execute();
self::assertCount(2, $query->getParameters());
self::assertSame(0, $query->getParameter(0)->getValue());
self::assertSame('bar', $query->getParameter('username')->getValue());
}
}
@@ -0,0 +1,108 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\OrmFunctionalTestCase;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
use Doctrine\Tests\Models\ECommerce\ECommerceCategory;
use Doctrine\Common\Collections\Criteria;
final class GH6740Test extends OrmFunctionalTestCase
{
/**
* @var int
*/
private $productId;
/**
* @var int
*/
private $firstCategoryId;
/**
* @var int
*/
private $secondCategoryId;
public function setUp()
{
$this->useModelSet('ecommerce');
parent::setUp();
$product = new ECommerceProduct();
$product->setName('First Product');
$firstCategory = new ECommerceCategory();
$secondCategory = new ECommerceCategory();
$firstCategory->setName('Business');
$secondCategory->setName('Home');
$product->addCategory($firstCategory);
$product->addCategory($secondCategory);
$this->_em->persist($product);
$this->_em->flush();
$this->_em->clear();
$this->productId = $product->getId();
$this->firstCategoryId = $firstCategory->getId();
$this->secondCategoryId = $secondCategory->getId();
}
/**
* @group 6740
*/
public function testCollectionFilteringLteOperator()
{
$product = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $this->productId);
$criteria = Criteria::create()->where(Criteria::expr()->lte('id', $this->secondCategoryId));
self::assertCount(2, $product->getCategories()->matching($criteria));
}
/**
* @group 6740
*/
public function testCollectionFilteringLtOperator()
{
$product = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $this->productId);
$criteria = Criteria::create()->where(Criteria::expr()->lt('id', $this->secondCategoryId));
self::assertCount(1, $product->getCategories()->matching($criteria));
}
/**
* @group 6740
*/
public function testCollectionFilteringGteOperator()
{
$product = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $this->productId);
$criteria = Criteria::create()->where(Criteria::expr()->gte('id', $this->firstCategoryId));
self::assertCount(2, $product->getCategories()->matching($criteria));
}
/**
* @group 6740
*/
public function testCollectionFilteringGtOperator()
{
$product = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $this->productId);
$criteria = Criteria::create()->where(Criteria::expr()->gt('id', $this->firstCategoryId));
self::assertCount(1, $product->getCategories()->matching($criteria));
}
/**
* @group 6740
*/
public function testCollectionFilteringEqualsOperator()
{
$product = $this->_em->find('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $this->productId);
$criteria = Criteria::create()->where(Criteria::expr()->eq('id', $this->firstCategoryId));
self::assertCount(1, $product->getCategories()->matching($criteria));
}
}
@@ -0,0 +1,63 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\ORM\Events;
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @covers \Doctrine\ORM\Internal\Hydration\AbstractHydrator
*/
class AbstractHydratorTest extends OrmFunctionalTestCase
{
/**
* @group DDC-3146
* @group #1515
*
* Verify that the number of added events to the event listener from the abstract hydrator class is equal to the
* number of removed events
*/
public function testOnClearEventListenerIsDetachedOnCleanup()
{
$mockConnection = $this->getMockBuilder('Doctrine\DBAL\Connection')->disableOriginalConstructor()->getMock();
$mockEntityManagerInterface = $this->getMock('Doctrine\ORM\EntityManagerInterface');
$mockEventManager = $this->getMock('Doctrine\Common\EventManager');
$mockStatement = $this->getMock('Doctrine\DBAL\Driver\Statement');
$mockResultMapping = $this->getMock('Doctrine\ORM\Query\ResultSetMapping');
$mockEntityManagerInterface->expects(self::any())->method('getEventManager')->willReturn($mockEventManager);
$mockEntityManagerInterface->expects(self::any())->method('getConnection')->willReturn($mockConnection);
$mockStatement->expects(self::once())->method('fetch')->willReturn(false);
/* @var $mockAbstractHydrator AbstractHydrator */
$mockAbstractHydrator = $this
->getMockBuilder('Doctrine\ORM\Internal\Hydration\AbstractHydrator')
->setConstructorArgs([$mockEntityManagerInterface])
->setMethods(['hydrateAllData'])
->getMock();
$mockEventManager
->expects(self::at(0))
->method('addEventListener')
->with([Events::onClear], $mockAbstractHydrator);
$mockEventManager
->expects(self::at(1))
->method('removeEventListener')
->with([Events::onClear], $mockAbstractHydrator);
$mockEventManager
->expects(self::at(2))
->method('addEventListener')
->with([Events::onClear], $mockAbstractHydrator);
$mockEventManager
->expects(self::at(3))
->method('removeEventListener')
->with([Events::onClear], $mockAbstractHydrator);
iterator_to_array($mockAbstractHydrator->iterate($mockStatement, $mockResultMapping));
$mockAbstractHydrator->hydrateAll($mockStatement, $mockResultMapping);
}
}
@@ -2,37 +2,58 @@
namespace Doctrine\Tests\ORM\Id;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Id\SequenceGenerator;
use Doctrine\Tests\Mocks\ConnectionMock;
use Doctrine\Tests\Mocks\StatementArrayMock;
use Doctrine\Tests\OrmTestCase;
/**
* Description of SequenceGeneratorTest
*
* @author robo
*/
class SequenceGeneratorTest extends \Doctrine\Tests\OrmTestCase
class SequenceGeneratorTest extends OrmTestCase
{
private $_em;
private $_seqGen;
/**
* @var EntityManager
*/
private $entityManager;
/**
* @var SequenceGenerator
*/
private $sequenceGenerator;
/**
* @var ConnectionMock
*/
private $connection;
protected function setUp()
{
$this->_em = $this->_getTestEntityManager();
$this->_seqGen = new SequenceGenerator('seq', 10);
parent::setUp();
$this->entityManager = $this->_getTestEntityManager();
$this->sequenceGenerator = new SequenceGenerator('seq', 10);
$this->connection = $this->entityManager->getConnection();
self::assertInstanceOf('Doctrine\Tests\Mocks\ConnectionMock', $this->connection);
}
public function testGeneration()
{
for ($i=0; $i < 42; ++$i) {
$this->connection->setFetchOneException(new \BadMethodCallException(
'Fetch* method used. Query method should be used instead, '
. 'as NEXTVAL should be run on a master server in master-slave setup.'
));
for ($i = 0; $i < 42; ++$i) {
if ($i % 10 == 0) {
$this->_em->getConnection()->setFetchOneResult((int)($i / 10) * 10);
$this->connection->setQueryResult(new StatementArrayMock([[(int)($i / 10) * 10]]));
}
$id = $this->_seqGen->generate($this->_em, null);
$this->assertEquals($i, $id);
$this->assertEquals((int)($i / 10) * 10 + 10, $this->_seqGen->getCurrentMaxValue());
$this->assertEquals($i + 1, $this->_seqGen->getNextValue());
$id = $this->sequenceGenerator->generate($this->entityManager, null);
self::assertSame($i, $id);
self::assertSame((int)($i / 10) * 10 + 10, $this->sequenceGenerator->getCurrentMaxValue());
self::assertSame($i + 1, $this->sequenceGenerator->getNextValue());
}
}
}
@@ -1083,15 +1083,19 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
/**
* @group DDC-2662
* @group 6682
*/
public function testQuotedSequenceName()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new RuntimeReflectionService());
$cm->initializeReflection(new RuntimeReflectionService());
$cm->setSequenceGeneratorDefinition(array('sequenceName' => '`foo`'));
$this->assertEquals(array('sequenceName' => 'foo', 'quoted' => true), $cm->sequenceGeneratorDefinition);
self::assertSame(
array('sequenceName' => 'foo', 'quoted' => true, 'allocationSize' => '1', 'initialValue' => '1'),
$cm->sequenceGeneratorDefinition
);
}
/**
@@ -4,6 +4,7 @@ namespace Doctrine\Tests\ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\UnitOfWork;
use Doctrine\Tests\Mocks\ConnectionMock;
use Doctrine\Tests\Mocks\DriverMock;
use Doctrine\Tests\Mocks\EntityManagerMock;
@@ -23,7 +24,7 @@ class PersistentCollectionTest extends OrmTestCase
protected $collection;
/**
* @var \Doctrine\ORM\EntityManagerInterface
* @var EntityManagerMock
*/
private $_emMock;
@@ -32,6 +33,8 @@ class PersistentCollectionTest extends OrmTestCase
parent::setUp();
$this->_emMock = EntityManagerMock::create(new ConnectionMock([], new DriverMock()));
$this->setUpPersistentCollection();
}
/**
@@ -58,7 +61,6 @@ class PersistentCollectionTest extends OrmTestCase
*/
public function testCurrentInitializesCollection()
{
$this->setUpPersistentCollection();
$this->collection->current();
$this->assertTrue($this->collection->isInitialized());
}
@@ -68,7 +70,6 @@ class PersistentCollectionTest extends OrmTestCase
*/
public function testKeyInitializesCollection()
{
$this->setUpPersistentCollection();
$this->collection->key();
$this->assertTrue($this->collection->isInitialized());
}
@@ -78,7 +79,6 @@ class PersistentCollectionTest extends OrmTestCase
*/
public function testNextInitializesCollection()
{
$this->setUpPersistentCollection();
$this->collection->next();
$this->assertTrue($this->collection->isInitialized());
}
@@ -88,12 +88,12 @@ class PersistentCollectionTest extends OrmTestCase
*/
public function testRemovingElementsAlsoRemovesKeys()
{
$this->setUpPersistentCollection();
$dummy = new \stdClass();
$this->collection->add('dummy');
$this->collection->add($dummy);
$this->assertEquals([0], array_keys($this->collection->toArray()));
$this->collection->removeElement('dummy');
$this->collection->removeElement($dummy);
$this->assertEquals([], array_keys($this->collection->toArray()));
}
@@ -102,9 +102,7 @@ class PersistentCollectionTest extends OrmTestCase
*/
public function testClearWillAlsoClearKeys()
{
$this->setUpPersistentCollection();
$this->collection->add('dummy');
$this->collection->add(new \stdClass());
$this->collection->clear();
$this->assertEquals([], array_keys($this->collection->toArray()));
}
@@ -114,12 +112,142 @@ class PersistentCollectionTest extends OrmTestCase
*/
public function testClearWillAlsoResetKeyPositions()
{
$this->setUpPersistentCollection();
$dummy = new \stdClass();
$this->collection->add('dummy');
$this->collection->removeElement('dummy');
$this->collection->add($dummy);
$this->collection->removeElement($dummy);
$this->collection->clear();
$this->collection->add('dummy');
$this->collection->add($dummy);
$this->assertEquals([0], array_keys($this->collection->toArray()));
}
/**
* @group 6613
* @group 6614
* @group 6616
*/
public function testWillKeepNewItemsInDirtyCollectionAfterInitialization()
{
/* @var $unitOfWork UnitOfWork|\PHPUnit_Framework_MockObject_MockObject */
$unitOfWork = $this
->getMockBuilder('Doctrine\ORM\UnitOfWork')
->disableOriginalConstructor()
->getMock();
$this->_emMock->setUnitOfWork($unitOfWork);
$newElement = new \stdClass();
$persistedElement = new \stdClass();
$this->collection->add($newElement);
self::assertFalse($this->collection->isInitialized());
self::assertTrue($this->collection->isDirty());
$unitOfWork
->expects(self::once())
->method('loadCollection')
->with($this->collection)
->willReturnCallback(function (PersistentCollection $persistentCollection) use ($persistedElement) {
$persistentCollection->unwrap()->add($persistedElement);
});
$this->collection->initialize();
self::assertSame([$persistedElement, $newElement], $this->collection->toArray());
self::assertTrue($this->collection->isInitialized());
self::assertTrue($this->collection->isDirty());
}
/**
* @group 6613
* @group 6614
* @group 6616
*/
public function testWillDeDuplicateNewItemsThatWerePreviouslyPersistedInDirtyCollectionAfterInitialization()
{
/* @var $unitOfWork UnitOfWork|\PHPUnit_Framework_MockObject_MockObject */
$unitOfWork = $this
->getMockBuilder('Doctrine\ORM\UnitOfWork')
->disableOriginalConstructor()
->getMock();
$this->_emMock->setUnitOfWork($unitOfWork);
$newElement = new \stdClass();
$newElementThatIsAlsoPersisted = new \stdClass();
$persistedElement = new \stdClass();
$this->collection->add($newElementThatIsAlsoPersisted);
$this->collection->add($newElement);
self::assertFalse($this->collection->isInitialized());
self::assertTrue($this->collection->isDirty());
$unitOfWork
->expects(self::once())
->method('loadCollection')
->with($this->collection)
->willReturnCallback(function (PersistentCollection $persistentCollection) use (
$persistedElement,
$newElementThatIsAlsoPersisted
) {
$persistentCollection->unwrap()->add($newElementThatIsAlsoPersisted);
$persistentCollection->unwrap()->add($persistedElement);
});
$this->collection->initialize();
self::assertSame(
[$newElementThatIsAlsoPersisted, $persistedElement, $newElement],
$this->collection->toArray()
);
self::assertTrue($this->collection->isInitialized());
self::assertTrue($this->collection->isDirty());
}
/**
* @group 6613
* @group 6614
* @group 6616
*/
public function testWillNotMarkCollectionAsDirtyAfterInitializationIfNoElementsWereAdded()
{
/* @var $unitOfWork UnitOfWork|\PHPUnit_Framework_MockObject_MockObject */
$unitOfWork = $this
->getMockBuilder('Doctrine\ORM\UnitOfWork')
->disableOriginalConstructor()
->getMock();
$this->_emMock->setUnitOfWork($unitOfWork);
$newElementThatIsAlsoPersisted = new \stdClass();
$persistedElement = new \stdClass();
$this->collection->add($newElementThatIsAlsoPersisted);
self::assertFalse($this->collection->isInitialized());
self::assertTrue($this->collection->isDirty());
$unitOfWork
->expects(self::once())
->method('loadCollection')
->with($this->collection)
->willReturnCallback(function (PersistentCollection $persistentCollection) use (
$persistedElement,
$newElementThatIsAlsoPersisted
) {
$persistentCollection->unwrap()->add($newElementThatIsAlsoPersisted);
$persistentCollection->unwrap()->add($persistedElement);
});
$this->collection->initialize();
self::assertSame(
[$newElementThatIsAlsoPersisted, $persistedElement],
$this->collection->toArray()
);
self::assertTrue($this->collection->isInitialized());
self::assertFalse($this->collection->isDirty());
}
}
@@ -71,6 +71,33 @@ class ProxyFactoryTest extends \Doctrine\Tests\OrmTestCase
$proxy->getDescription();
}
public function testSkipMappedSuperClassesOnGeneration()
{
$cm = new ClassMetadata('stdClass');
$cm->isMappedSuperclass = true;
self::assertSame(
0,
$this->proxyFactory->generateProxyClasses([$cm]),
'No proxies generated.'
);
}
/**
* @group 6625
*/
public function testSkipEmbeddableClassesOnGeneration()
{
$cm = new ClassMetadata('stdClass');
$cm->isEmbeddedClass = true;
self::assertSame(
0,
$this->proxyFactory->generateProxyClasses([$cm]),
'No proxies generated.'
);
}
/**
* @group DDC-1771
*/
@@ -197,4 +197,66 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase
$q2 = clone $query;
$this->assertSame($config->getDefaultQueryHints(), $q2->getHints());
}
/**
* @group 6699
*/
public function testGetParameterTypeJuggling()
{
$query = $this->_em->createQuery('select u from Doctrine\Tests\Models\CMS\CmsUser u where u.id = ?0');
$query->setParameter(0, 0);
self::assertCount(1, $query->getParameters());
self::assertSame(0, $query->getParameter(0)->getValue());
self::assertSame(0, $query->getParameter('0')->getValue());
}
/**
* @group 6699
*/
public function testSetParameterWithNameZeroIsNotOverridden()
{
$query = $this->_em->createQuery('select u from Doctrine\Tests\Models\CMS\CmsUser u where u.id != ?0 and u.username = :name');
$query->setParameter(0, 0);
$query->setParameter('name', 'Doctrine');
self::assertCount(2, $query->getParameters());
self::assertSame(0, $query->getParameter('0')->getValue());
self::assertSame('Doctrine', $query->getParameter('name')->getValue());
}
/**
* @group 6699
*/
public function testSetParameterWithNameZeroDoesNotOverrideAnotherParameter()
{
$query = $this->_em->createQuery('select u from Doctrine\Tests\Models\CMS\CmsUser u where u.id != ?0 and u.username = :name');
$query->setParameter('name', 'Doctrine');
$query->setParameter(0, 0);
self::assertCount(2, $query->getParameters());
self::assertSame(0, $query->getParameter(0)->getValue());
self::assertSame('Doctrine', $query->getParameter('name')->getValue());
}
/**
* @group 6699
*/
public function testSetParameterWithTypeJugglingWorks()
{
$query = $this->_em->createQuery('select u from Doctrine\Tests\Models\CMS\CmsUser u where u.id != ?0 and u.username = :name');
$query->setParameter('0', 1);
$query->setParameter('name', 'Doctrine');
$query->setParameter(0, 2);
$query->setParameter('0', 3);
self::assertCount(2, $query->getParameters());
self::assertSame(3, $query->getParameter(0)->getValue());
self::assertSame(3, $query->getParameter('0')->getValue());
self::assertSame('Doctrine', $query->getParameter('name')->getValue());
}
}
@@ -153,12 +153,12 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c0_.discr AS discr_5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id INNER JOIN company_managers c2_ INNER JOIN company_employees c4_ ON c2_.id = c4_.id INNER JOIN company_persons c3_ ON c2_.id = c3_.id AND (c0_.id = c3_.id)'
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c0_.discr AS discr_5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id INNER JOIN (company_managers c2_ INNER JOIN company_employees c4_ ON c2_.id = c4_.id INNER JOIN company_persons c3_ ON c2_.id = c3_.id) ON (c0_.id = c3_.id)'
);
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c0_.discr AS discr_5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ INNER JOIN company_employees c4_ ON c2_.id = c4_.id INNER JOIN company_persons c3_ ON c2_.id = c3_.id ON (c0_.id = c3_.id)'
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c0_.discr AS discr_5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN (company_managers c2_ INNER JOIN company_employees c4_ ON c2_.id = c4_.id INNER JOIN company_persons c3_ ON c2_.id = c3_.id) ON (c0_.id = c3_.id)'
);
}
@@ -2165,7 +2165,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
// the where clause when not joining onto that table
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c LEFT JOIN Doctrine\Tests\Models\Company\CompanyEmployee e WITH e.id = c.salesPerson WHERE c.completed = true',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6 FROM company_contracts c0_ LEFT JOIN company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id ON (c2_.id = c0_.salesPerson_id) WHERE (c0_.completed = 1) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6 FROM company_contracts c0_ LEFT JOIN (company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id) ON (c2_.id = c0_.salesPerson_id) WHERE (c0_.completed = 1) AND c0_.discr IN ('fix', 'flexible', 'flexultra')"
);
}
@@ -1172,4 +1172,81 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(['u', 'g'], $aliases);
}
/**
* @group 6699
*/
public function testGetParameterTypeJuggling()
{
$builder = $this->_em->createQueryBuilder()
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where('u.id = ?0');
$builder->setParameter(0, 0);
self::assertCount(1, $builder->getParameters());
self::assertSame(0, $builder->getParameter(0)->getValue());
self::assertSame(0, $builder->getParameter('0')->getValue());
}
/**
* @group 6699
*/
public function testSetParameterWithNameZeroIsNotOverridden()
{
$builder = $this->_em->createQueryBuilder()
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where('u.id != ?0')
->andWhere('u.username = :name');
$builder->setParameter(0, 0);
$builder->setParameter('name', 'Doctrine');
self::assertCount(2, $builder->getParameters());
self::assertSame(0, $builder->getParameter('0')->getValue());
self::assertSame('Doctrine', $builder->getParameter('name')->getValue());
}
/**
* @group 6699
*/
public function testSetParameterWithNameZeroDoesNotOverrideAnotherParameter()
{
$builder = $this->_em->createQueryBuilder()
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where('u.id != ?0')
->andWhere('u.username = :name');
$builder->setParameter('name', 'Doctrine');
$builder->setParameter(0, 0);
self::assertCount(2, $builder->getParameters());
self::assertSame(0, $builder->getParameter(0)->getValue());
self::assertSame('Doctrine', $builder->getParameter('name')->getValue());
}
/**
* @group 6699
*/
public function testSetParameterWithTypeJugglingWorks()
{
$builder = $this->_em->createQueryBuilder()
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where('u.id != ?0')
->andWhere('u.username = :name');
$builder->setParameter('0', 1);
$builder->setParameter('name', 'Doctrine');
$builder->setParameter(0, 2);
$builder->setParameter('0', 3);
self::assertCount(2, $builder->getParameters());
self::assertSame(3, $builder->getParameter(0)->getValue());
self::assertSame(3, $builder->getParameter('0')->getValue());
self::assertSame('Doctrine', $builder->getParameter('name')->getValue());
}
}
@@ -0,0 +1,195 @@
<?php
namespace Doctrine\Tests\ORM\Tools\Console;
use Doctrine\ORM\Tools\Console\MetadataFilter;
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
/**
* Tests for {@see \Doctrine\ORM\Tools\Console\MetadataFilter}
*
* @covers \Doctrine\ORM\Tools\Console\MetadataFilter
*/
class MetadataFilterTest extends \Doctrine\Tests\OrmTestCase
{
/**
* @var DisconnectedClassMetadataFactory
*/
private $cmf;
protected function setUp()
{
parent::setUp();
$driver = $this->createAnnotationDriver();
$em = $this->_getTestEntityManager();
$em->getConfiguration()->setMetadataDriverImpl($driver);
$this->cmf = new DisconnectedClassMetadataFactory();
$this->cmf->setEntityManager($em);
}
public function testFilterWithEmptyArray()
{
$originalMetadatas = array(
$metadataAaa = $this->cmf->getMetadataFor(MetadataFilterTestEntityAaa::CLASSNAME),
$metadataBbb = $this->cmf->getMetadataFor(MetadataFilterTestEntityBbb::CLASSNAME),
);
$metadatas = $originalMetadatas;
$metadatas = MetadataFilter::filter($metadatas, array());
$this->assertContains($metadataAaa, $metadatas);
$this->assertContains($metadataBbb, $metadatas);
$this->assertCount(count($originalMetadatas), $metadatas);
}
public function testFilterWithString()
{
$originalMetadatas = array(
$metadataAaa = $this->cmf->getMetadataFor(MetadataFilterTestEntityAaa::CLASSNAME),
$metadataBbb = $this->cmf->getMetadataFor(MetadataFilterTestEntityBbb::CLASSNAME),
$metadataCcc = $this->cmf->getMetadataFor(MetadataFilterTestEntityCcc::CLASSNAME),
);
$metadatas = $originalMetadatas;
$metadatas = MetadataFilter::filter($metadatas, 'MetadataFilterTestEntityAaa');
$this->assertContains($metadataAaa, $metadatas);
$this->assertNotContains($metadataBbb, $metadatas);
$this->assertNotContains($metadataCcc, $metadatas);
$this->assertCount(1, $metadatas);
$metadatas = $originalMetadatas;
$metadatas = MetadataFilter::filter($metadatas, 'MetadataFilterTestEntityBbb');
$this->assertNotContains($metadataAaa, $metadatas);
$this->assertContains($metadataBbb, $metadatas);
$this->assertNotContains($metadataCcc, $metadatas);
$this->assertCount(1, $metadatas);
$metadatas = $originalMetadatas;
$metadatas = MetadataFilter::filter($metadatas, 'MetadataFilterTestEntityCcc');
$this->assertNotContains($metadataAaa, $metadatas);
$this->assertNotContains($metadataBbb, $metadatas);
$this->assertContains($metadataCcc, $metadatas);
$this->assertCount(1, $metadatas);
}
public function testFilterWithString2()
{
$originalMetadatas = array(
$metadataFoo = $this->cmf->getMetadataFor(MetadataFilterTestEntityFoo::CLASSNAME),
$metadataFooBar = $this->cmf->getMetadataFor(MetadataFilterTestEntityFooBar::CLASSNAME),
$metadataBar = $this->cmf->getMetadataFor(MetadataFilterTestEntityBar::CLASSNAME),
);
$metadatas = $originalMetadatas;
$metadatas = MetadataFilter::filter($metadatas, 'MetadataFilterTestEntityFoo');
$this->assertContains($metadataFoo, $metadatas);
$this->assertContains($metadataFooBar, $metadatas);
$this->assertNotContains($metadataBar, $metadatas);
$this->assertCount(2, $metadatas);
}
public function testFilterWithArray()
{
$originalMetadatas = array(
$metadataAaa = $this->cmf->getMetadataFor(MetadataFilterTestEntityAaa::CLASSNAME),
$metadataBbb = $this->cmf->getMetadataFor(MetadataFilterTestEntityBbb::CLASSNAME),
$metadataCcc = $this->cmf->getMetadataFor(MetadataFilterTestEntityCcc::CLASSNAME),
);
$metadatas = $originalMetadatas;
$metadatas = MetadataFilter::filter($metadatas, array(
'MetadataFilterTestEntityAaa',
'MetadataFilterTestEntityCcc',
));
$this->assertContains($metadataAaa, $metadatas);
$this->assertNotContains($metadataBbb, $metadatas);
$this->assertContains($metadataCcc, $metadatas);
$this->assertCount(2, $metadatas);
}
public function testFilterWithRegex()
{
$originalMetadatas = array(
$metadataFoo = $this->cmf->getMetadataFor(MetadataFilterTestEntityFoo::CLASSNAME),
$metadataFooBar = $this->cmf->getMetadataFor(MetadataFilterTestEntityFooBar::CLASSNAME),
$metadataBar = $this->cmf->getMetadataFor(MetadataFilterTestEntityBar::CLASSNAME),
);
$metadatas = $originalMetadatas;
$metadatas = MetadataFilter::filter($metadatas, 'Foo$');
$this->assertContains($metadataFoo, $metadatas);
$this->assertNotContains($metadataFooBar, $metadatas);
$this->assertNotContains($metadataBar, $metadatas);
$this->assertCount(1, $metadatas);
$metadatas = $originalMetadatas;
$metadatas = MetadataFilter::filter($metadatas, 'Bar$');
$this->assertNotContains($metadataFoo, $metadatas);
$this->assertContains($metadataFooBar, $metadatas);
$this->assertContains($metadataBar, $metadatas);
$this->assertCount(2, $metadatas);
}
}
/** @Entity */
class MetadataFilterTestEntityAaa
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") */
protected $id;
}
/** @Entity */
class MetadataFilterTestEntityBbb
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") */
protected $id;
}
/** @Entity */
class MetadataFilterTestEntityCcc
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") */
protected $id;
}
/** @Entity */
class MetadataFilterTestEntityFoo
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") */
protected $id;
}
/** @Entity */
class MetadataFilterTestEntityBar
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") */
protected $id;
}
/** @Entity */
class MetadataFilterTestEntityFooBar
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="integer") */
protected $id;
}
@@ -30,6 +30,18 @@ class CountOutputWalkerTest extends PaginationTestCase
);
}
public function testCountQuery_GroupBy()
{
$query = $this->entityManager->createQuery(
'SELECT p.name FROM Doctrine\Tests\ORM\Tools\Pagination\Person p GROUP BY p.name');
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
$query->setFirstResult(null)->setMaxResults(null);
$this->assertSame(
"SELECT COUNT(*) AS dctrn_count FROM (SELECT p0_.name AS name_0 FROM Person p0_ GROUP BY p0_.name) dctrn_table", $query->getSQL()
);
}
public function testCountQuery_Having()
{
$query = $this->entityManager->createQuery(
@@ -37,8 +49,8 @@ class CountOutputWalkerTest extends PaginationTestCase
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
$query->setFirstResult(null)->setMaxResults(null);
$this->assertEquals(
"SELECT COUNT(*) AS dctrn_count FROM (SELECT DISTINCT id_1 FROM (SELECT count(u0_.id) AS sclr_0, g1_.id AS id_1, u0_.id AS id_2 FROM groups g1_ LEFT JOIN user_group u2_ ON g1_.id = u2_.group_id LEFT JOIN User u0_ ON u0_.id = u2_.user_id GROUP BY g1_.id HAVING sclr_0 > 0) dctrn_result) dctrn_table", $query->getSql()
$this->assertSame(
"SELECT COUNT(*) AS dctrn_count FROM (SELECT count(u0_.id) AS sclr_0, g1_.id AS id_1, u0_.id AS id_2 FROM groups g1_ LEFT JOIN user_group u2_ ON g1_.id = u2_.group_id LEFT JOIN User u0_ ON u0_.id = u2_.user_id GROUP BY g1_.id HAVING sclr_0 > 0) dctrn_table", $query->getSQL()
);
}
@@ -2,10 +2,11 @@
namespace Doctrine\Tests\ORM\Tools;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\ORM\Tools\ToolEvents;
use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs;
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
{
@@ -138,6 +139,26 @@ class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
$this->assertTrue($table->hasIndex('primary'));
$this->assertTrue($table->hasIndex('uniq_hash'));
}
public function testSetDiscriminatorColumnWithoutLength()
{
$em = $this->_getTestEntityManager();
$schemaTool = new SchemaTool($em);
$metadata = $em->getClassMetadata(__NAMESPACE__ . '\\FirstEntity');
$metadata->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
$metadata->setDiscriminatorColumn(['name' => 'discriminator', 'type' => 'string']);
$schema = $schemaTool->getSchemaFromMetadata([$metadata]);
$this->assertTrue($schema->hasTable('first_entity'));
$table = $schema->getTable('first_entity');
$this->assertTrue($table->hasColumn('discriminator'));
$column = $table->getColumn('discriminator');
$this->assertEquals(255, $column->getLength());
}
}
/**
@@ -187,3 +208,45 @@ class UniqueConstraintAnnotationModel
*/
private $hash;
}
/**
* @Entity
* @Table(name="first_entity")
*/
class FirstEntity
{
/**
* @Id
* @Column(name="id")
*/
public $id;
/**
* @OneToOne(targetEntity="SecondEntity")
* @JoinColumn(name="id", referencedColumnName="fist_entity_id")
*/
public $secondEntity;
/**
* @Column(name="name")
*/
public $name;
}
/**
* @Entity
* @Table(name="second_entity")
*/
class SecondEntity
{
/**
* @Id
* @Column(name="fist_entity_id")
*/
public $fist_entity_id;
/**
* @Column(name="name")
*/
public $name;
}
+38 -1
View File
@@ -68,6 +68,43 @@ class SetupTest extends \Doctrine\Tests\OrmTestCase
$this->assertInstanceOf('Doctrine\ORM\Mapping\Driver\YamlDriver', $config->getMetadataDriverImpl());
}
/**
* @group 5904
*/
public function testCacheNamespaceShouldBeGeneratedWhenCacheIsNotGiven()
{
$config = Setup::createConfiguration(false, '/foo');
$cache = $config->getMetadataCacheImpl();
self::assertSame('dc2_1effb2475fcfba4f9e8b8a1dbc8f3caf_', $cache->getNamespace());
}
/**
* @group 5904
*/
public function testCacheNamespaceShouldBeGeneratedWhenCacheIsGivenButHasNoNamespace()
{
$config = Setup::createConfiguration(false, '/foo', new ArrayCache());
$cache = $config->getMetadataCacheImpl();
self::assertSame('dc2_1effb2475fcfba4f9e8b8a1dbc8f3caf_', $cache->getNamespace());
}
/**
* @group 5904
*/
public function testConfiguredCacheNamespaceShouldBeUsedAsPrefixOfGeneratedNamespace()
{
$originalCache = new ArrayCache();
$originalCache->setNamespace('foo');
$config = Setup::createConfiguration(false, '/foo', $originalCache);
$cache = $config->getMetadataCacheImpl();
self::assertSame($originalCache, $cache);
self::assertSame('foo:dc2_1effb2475fcfba4f9e8b8a1dbc8f3caf_', $cache->getNamespace());
}
/**
* @group DDC-1350
*/
@@ -98,7 +135,7 @@ class SetupTest extends \Doctrine\Tests\OrmTestCase
$cache = $this->getMock('Doctrine\Common\Cache\Cache');
$cache->expects($this->never())->method('setNamespace');
$config = Setup::createConfiguration(array(), true, $cache);
$config = Setup::createConfiguration(true, null, $cache);
$this->assertSame($cache, $config->getResultCacheImpl());
$this->assertSame($cache, $config->getMetadataCacheImpl());
@@ -309,6 +309,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
protected function tearDown()
{
$conn = static::$_sharedConn;
// In case test is skipped, tearDown is called, but no setup may have run
if ( ! $conn) {
return;
}
$platform = $conn->getDatabasePlatform();
$this->_sqlLoggerStack->enabled = false;