mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 06:52:09 +01:00
Compare commits
117 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1647229cd | ||
|
|
9111d794d5 | ||
|
|
34ec1e3248 | ||
|
|
3c52fa5ea6 | ||
|
|
b3ed478fb4 | ||
|
|
c5973f8019 | ||
|
|
6512902eae | ||
|
|
798a8bca92 | ||
|
|
7bca37e827 | ||
|
|
818a5d5904 | ||
|
|
20ac6f383c | ||
|
|
60d97e068c | ||
|
|
94162d1c03 | ||
|
|
1c042b5b8d | ||
|
|
b770a6687a | ||
|
|
0abf2484ce | ||
|
|
7d8aa2213d | ||
|
|
12a639d4a2 | ||
|
|
432a035baa | ||
|
|
97df2f8749 | ||
|
|
61aec8fdcd | ||
|
|
292fbd9756 | ||
|
|
c2112c0584 | ||
|
|
05c7e0055a | ||
|
|
fb7b5c6fb1 | ||
|
|
da0e3439ab | ||
|
|
a1df81e18c | ||
|
|
1dea57013c | ||
|
|
91b1a25bb2 | ||
|
|
473ba2f04c | ||
|
|
e80eae4c98 | ||
|
|
68184a3803 | ||
|
|
3412ef935a | ||
|
|
4215a24969 | ||
|
|
02d8802570 | ||
|
|
0e107880cf | ||
|
|
3b259dcb42 | ||
|
|
d87e90d392 | ||
|
|
c1ad170bed | ||
|
|
565962ec8b | ||
|
|
eb9812feb5 | ||
|
|
d9b39f6fce | ||
|
|
b1db2ad0d8 | ||
|
|
92b3d0a383 | ||
|
|
fc8997a935 | ||
|
|
88d937cc89 | ||
|
|
bff55577cd | ||
|
|
7ff30e273a | ||
|
|
9c81989349 | ||
|
|
e0bb84e1da | ||
|
|
692f423047 | ||
|
|
0814e8abc7 | ||
|
|
d4a1ea8995 | ||
|
|
c2febabdd0 | ||
|
|
633e342d82 | ||
|
|
2e7318dcc2 | ||
|
|
6b3edbbbf9 | ||
|
|
fdcb46e780 | ||
|
|
6da0314deb | ||
|
|
b61d109fe2 | ||
|
|
960c94f661 | ||
|
|
515b0205c6 | ||
|
|
d76c5b11f6 | ||
|
|
88043577a4 | ||
|
|
d0b9f7cb2b | ||
|
|
10a3f5e10e | ||
|
|
eeddaecd26 | ||
|
|
50f7f3a48e | ||
|
|
e94a293446 | ||
|
|
08e5e47780 | ||
|
|
e3a5ffbb55 | ||
|
|
bf06c3418b | ||
|
|
6a8172902a | ||
|
|
d9328ea5e7 | ||
|
|
8cd8c993c8 | ||
|
|
f45d8f488b | ||
|
|
6257daf097 | ||
|
|
d46910f6bb | ||
|
|
5c4e3d9bd0 | ||
|
|
7d0d06cd9a | ||
|
|
e4f49231bf | ||
|
|
ca600f466e | ||
|
|
01d6b73f78 | ||
|
|
c36b1f1d00 | ||
|
|
588f7fc765 | ||
|
|
1becb8dfd5 | ||
|
|
394447d92d | ||
|
|
f834c61a2b | ||
|
|
67cf5b7160 | ||
|
|
e3a04c3458 | ||
|
|
cb7e27460e | ||
|
|
9dc5c5ddce | ||
|
|
bbd01ea457 | ||
|
|
360c578c5d | ||
|
|
ca289bf1ea | ||
|
|
17341cf051 | ||
|
|
5638b8c5c0 | ||
|
|
ccaf00cfab | ||
|
|
b57f4ecb52 | ||
|
|
7ae96dd9c7 | ||
|
|
0b3b4ecef6 | ||
|
|
8e3fc30477 | ||
|
|
db2c51d860 | ||
|
|
b6ac1b4962 | ||
|
|
7734e3e2ec | ||
|
|
45494fd6a0 | ||
|
|
efad33a70e | ||
|
|
ba9feb1519 | ||
|
|
4683d76c52 | ||
|
|
4ddd4a68ef | ||
|
|
d9f9228d95 | ||
|
|
ef4d8410f6 | ||
|
|
a62cd45476 | ||
|
|
7369a2de68 | ||
|
|
623ab9cee9 | ||
|
|
52c75d1633 | ||
|
|
8875d549eb |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
build.properties
|
||||
build/
|
||||
logs/
|
||||
reports/
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -10,3 +10,6 @@
|
||||
[submodule "lib/vendor/Symfony/Component/Yaml"]
|
||||
path = lib/vendor/Symfony/Component/Yaml
|
||||
url = git://github.com/symfony/Yaml.git
|
||||
[submodule "lib/vendor/doctrine-build-common"]
|
||||
path = lib/vendor/doctrine-build-common
|
||||
url = https://github.com/doctrine/doctrine-build-common.git
|
||||
|
||||
19
.travis.yml
Normal file
19
.travis.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
env:
|
||||
- DB=mysql
|
||||
- DB=pgsql
|
||||
- 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"
|
||||
- git submodule update --init
|
||||
|
||||
script: phpunit --configuration tests/travis/$DB.travis.xml
|
||||
11
build.properties
Normal file
11
build.properties
Normal file
@@ -0,0 +1,11 @@
|
||||
# Project Name
|
||||
project.name=DoctrineORM
|
||||
|
||||
# Dependency minimum versions
|
||||
dependencies.common=2.1.0
|
||||
dependencies.dbal=2.1.0
|
||||
dependencies.sfconsole=2.0.0
|
||||
|
||||
# Version class and file
|
||||
project.version_class = Doctrine\ORM\Version
|
||||
project.version_file = lib/Doctrine/ORM/Version.php
|
||||
@@ -1,15 +0,0 @@
|
||||
version=2.0.0BETA2
|
||||
dependencies.common=2.0.0BETA4
|
||||
dependencies.dbal=2.0.0BETA4
|
||||
stability=beta
|
||||
build.dir=build
|
||||
dist.dir=dist
|
||||
report.dir=reports
|
||||
log.archive.dir=logs
|
||||
project.pirum_dir=
|
||||
project.download_dir=
|
||||
test.phpunit_configuration_file=
|
||||
test.phpunit_generate_coverage=0
|
||||
test.pmd_reports=0
|
||||
test.pdepend_exec=
|
||||
test.phpmd_exec=
|
||||
221
build.xml
221
build.xml
@@ -1,11 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
Doctrine 2 build file.
|
||||
-->
|
||||
|
||||
<project name="Doctrine2" default="build" basedir=".">
|
||||
<project name="DoctrineORM" default="build" basedir=".">
|
||||
<taskdef classname="phing.tasks.ext.d51PearPkg2Task" name="d51pearpkg2" />
|
||||
<import file="${project.basedir}/lib/vendor/doctrine-build-common/packaging.xml" />
|
||||
|
||||
<property file="build.properties" />
|
||||
|
||||
@@ -14,6 +10,8 @@
|
||||
-->
|
||||
<fileset id="shared-artifacts" dir=".">
|
||||
<include name="LICENSE"/>
|
||||
<include name="UPGRADE*" />
|
||||
<include name="doctrine-mapping.xsd" />
|
||||
</fileset>
|
||||
|
||||
<!--
|
||||
@@ -51,118 +49,34 @@
|
||||
-->
|
||||
<fileset id="symfony-sources" dir="./lib/vendor">
|
||||
<include name="Symfony/Component/**"/>
|
||||
<exclude name="**/.git/**" />
|
||||
</fileset>
|
||||
|
||||
<!--
|
||||
Clean the directory for the next build.
|
||||
-->
|
||||
<target name="clean">
|
||||
<available file="./build.properties" property="build_properties_exist" value="true"/>
|
||||
<fail unless="build_properties_exist" message="The build.properties file is missing." />
|
||||
|
||||
<delete dir="${build.dir}" includeemptydirs="true" />
|
||||
<delete dir="${dist.dir}" includeemptydirs="true" />
|
||||
<delete dir="${report.dir}" includeemptydirs="true" />
|
||||
</target>
|
||||
|
||||
<!--
|
||||
Prepare the new build directories after cleaning
|
||||
-->
|
||||
<target name="prepare" depends="clean">
|
||||
<echo msg="Creating build directory: ${build.dir}" />
|
||||
<mkdir dir="${build.dir}" />
|
||||
<echo msg="Creating distribution directory: ${dist.dir}" />
|
||||
<mkdir dir="${dist.dir}" />
|
||||
<echo msg="Creating report directory: ${report.dir}" />
|
||||
<mkdir dir="${report.dir}" />
|
||||
<mkdir dir="${build.dir}/logs"/>
|
||||
<mkdir dir="${report.dir}/tests"/>
|
||||
</target>
|
||||
|
||||
<!--
|
||||
Builds ORM package, preparing it for distribution.
|
||||
-->
|
||||
<target name="build-orm" depends="prepare">
|
||||
<exec command="grep '${version}' ${project.basedir}/lib/Doctrine/ORM/Version.php" checkreturn="true"/>
|
||||
<copy todir="${build.dir}/doctrine-orm">
|
||||
<target name="copy-files" depends="prepare">
|
||||
<copy todir="${build.dir}/${project.name}-${version}">
|
||||
<fileset refid="shared-artifacts"/>
|
||||
</copy>
|
||||
<copy todir="${build.dir}/doctrine-orm">
|
||||
<copy todir="${build.dir}/${project.name}-${version}">
|
||||
<fileset refid="common-sources"/>
|
||||
<fileset refid="dbal-sources"/>
|
||||
<fileset refid="orm-sources"/>
|
||||
</copy>
|
||||
<copy todir="${build.dir}/doctrine-orm/Doctrine">
|
||||
<copy todir="${build.dir}/${project.name}-${version}/Doctrine">
|
||||
<fileset refid="symfony-sources"/>
|
||||
</copy>
|
||||
<copy todir="${build.dir}/doctrine-orm/bin">
|
||||
<copy todir="${build.dir}/${project.name}-${version}/bin">
|
||||
<fileset refid="bin-scripts"/>
|
||||
</copy>
|
||||
<exec command="sed 's/${version}-DEV/${version}/' ${build.dir}/doctrine-orm/Doctrine/ORM/Version.php > ${build.dir}/doctrine-orm/Doctrine/ORM/Version2.php" passthru="true" />
|
||||
<exec command="mv ${build.dir}/doctrine-orm/Doctrine/ORM/Version2.php ${build.dir}/doctrine-orm/Doctrine/ORM/Version.php" passthru="true" />
|
||||
<delete dir="${build.dir}/doctrine-orm/Doctrine/Symfony/Component/Yaml/.git" includeemptydirs="true"/>
|
||||
<delete dir="${build.dir}/doctrine-orm/Doctrine/Symfony/Component/Console/.git" includeemptydirs="true"/>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="build" depends="test, build-orm"/>
|
||||
|
||||
<target name="package-phar" depends="build-orm">
|
||||
<pharpackage basedir="${build.dir}/doctrine-orm/" destfile="${dist.dir}/doctrine-orm-${version}.phar" clistub="${build.dir}/doctrine-orm/bin/doctrine.php" signature="sha512">
|
||||
<fileset dir="${build.dir}/doctrine-orm">
|
||||
<include name="**/**" />
|
||||
</fileset>
|
||||
<metadata>
|
||||
<element name="version" value="${version}" />
|
||||
<element name="authors">
|
||||
<element name="Guilherme Blanco"><element name="e-mail" value="guilhermeblanco@gmail.com" /></element>
|
||||
<element name="Benjamin Eberlei"><element name="e-mail" value="kontakt@beberlei.de" /></element>
|
||||
<element name="Jonathan H. Wage"><element name="e-mail" value="jonwage@gmail.com" /></element>
|
||||
<element name="Roman Borschel"><element name="e-mail" value="roman@code-factory.org" /></element>
|
||||
</element>
|
||||
</metadata>
|
||||
</pharpackage>
|
||||
</target>
|
||||
|
||||
<!--
|
||||
Runs the full test suite.
|
||||
-->
|
||||
<target name="test" depends="prepare">
|
||||
<if><equals arg1="${test.phpunit_generate_coverage}" arg2="1" />
|
||||
<then>
|
||||
<property name="test.phpunit_coverage_file" value="${build.dir}/logs/clover.xml" />
|
||||
</then>
|
||||
<else>
|
||||
<property name="test.phpunit_coverage_file" value="false" />
|
||||
</else>
|
||||
</if>
|
||||
|
||||
<nativephpunit
|
||||
testfile="./tests/Doctrine/Tests/AllTests.php" junitlogfile="${build.dir}/logs/testsuites.xml"
|
||||
testdirectory="./tests" coverageclover="${test.phpunit_coverage_file}" configuration="${test.phpunit_configuration_file}"
|
||||
/>
|
||||
<phpunitreport infile="${build.dir}/logs/testsuites.xml" format="frames" todir="${report.dir}/tests" />
|
||||
|
||||
<nativephpunit testfile="./tests/Doctrine/Tests/ORM/Performance/AllTests.php" testdirectory="./tests" haltonfailure="false" haltonerror="false" />
|
||||
<tstamp/>
|
||||
<copy file="${build.dir}/logs/testsuites.xml" tofile="${log.archive.dir}/latest/log.xml" overwrite="true"/>
|
||||
|
||||
<if><equals arg1="${test.pmd_reports}" arg2="1" />
|
||||
<then>
|
||||
<exec command="${test.pdepend_exec} --jdepend-xml=${build.dir}/logs/jdepend.xml ./lib/Doctrine" />
|
||||
<exec command="${test.phpmd_exec} ./lib/Doctrine xml codesize --reportfile ${build.dir}/logs/phpmd.xml" />
|
||||
|
||||
<copy file="${build.dir}/logs/jdepend.xml" tofile="${log.archive.dir}/latest/jdepend.xml" overwrite="true"/>
|
||||
<copy file="${build.dir}/logs/phpmd.xml" tofile="${log.archive.dir}/latest/phpmd.xml" overwrite="true"/>
|
||||
</then>
|
||||
</if>
|
||||
</target>
|
||||
|
||||
<!--
|
||||
Builds distributable PEAR packages.
|
||||
-->
|
||||
<target name="build-packages" depends="build-orm">
|
||||
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/doctrine-orm">
|
||||
<target name="define-pear-package" depends="copy-files">
|
||||
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/${project.name}-${version}">
|
||||
<name>DoctrineORM</name>
|
||||
<summary>Doctrine Object Relational Mapper</summary>
|
||||
<channel>pear.doctrine-project.org</channel>
|
||||
@@ -172,124 +86,29 @@
|
||||
<lead user="romanb" name="Roman Borschel" email="roman@code-factory.org" />
|
||||
<lead user="beberlei" name="Benjamin Eberlei" email="kontakt@beberlei.de" />
|
||||
<license>LGPL</license>
|
||||
<version release="${version}" api="${version}" />
|
||||
<stability release="${stability}" api="${stability}" />
|
||||
<version release="${pear.version}" api="${pear.version}" />
|
||||
<stability release="${pear.stability}" api="${pear.stability}" />
|
||||
<notes>-</notes>
|
||||
<dependencies>
|
||||
<php minimum_version="5.3.0" />
|
||||
<pear minimum_version="1.6.0" recommended_version="1.6.1" />
|
||||
<package name="DoctrineCommon" channel="pear.doctrine-project.org" minimum_version="${dependencies.common}" />
|
||||
<package name="DoctrineDBAL" channel="pear.doctrine-project.org" minimum_version="${dependencies.dbal}" />
|
||||
<package name="DoctrineSymfonyConsole" channel="pear.doctrine-project.org" minimum_version="2.0.0" />
|
||||
<package name="DoctrineSymfonyYaml" channel="pear.doctrine-project.org" minimum_version="2.0.0" />
|
||||
<package name="DoctrineCommon" channel="pear.doctrine-project.org" minimum_version="${dependencies.common}" maximum_version="2.1.99" />
|
||||
<package name="DoctrineDBAL" channel="pear.doctrine-project.org" minimum_version="${dependencies.dbal}" maximum_version="2.1.99" />
|
||||
<package name="Console" channel="pear.symfony.com" minimum_version="2.0.0" />
|
||||
<package name="Yaml" channel="pear.symfony.com" minimum_version="2.0.0" />
|
||||
</dependencies>
|
||||
<dirroles key="bin">script</dirroles>
|
||||
<ignore>Doctrine/Common/</ignore>
|
||||
<ignore>Doctrine/DBAL/</ignore>
|
||||
<ignore>Symfony/Component/Yaml/</ignore>
|
||||
<ignore>Symfony/Component/Yaml/</ignore>
|
||||
<ignore>Symfony/Component/Console/</ignore>
|
||||
<release>
|
||||
<install as="doctrine" name="bin/doctrine" />
|
||||
<install as="doctrine.php" name="bin/doctrine.php" />
|
||||
<install as="doctrine.bat" name="bin/doctrine.bat" />
|
||||
</release>
|
||||
<replacement path="bin/doctrine.bat" type="pear-config" from="@php_bin@" to="php_bin" />
|
||||
<replacement path="bin/doctrine" type="pear-config" from="@php_bin@" to="php_bin" />
|
||||
<replacement path="bin/doctrine.bat" type="pear-config" from="@bin_dir@" to="bin_dir" />
|
||||
</d51pearpkg2>
|
||||
<exec command="pear package" dir="${build.dir}/doctrine-orm" passthru="true" />
|
||||
<exec command="mv DoctrineORM-${version}.tgz ../../dist" dir="${build.dir}/doctrine-orm" passthru="true" />
|
||||
<tar destfile="dist/DoctrineORM-${version}-full.tar.gz" compression="gzip" basedir="${build.dir}">
|
||||
<fileset dir="${build.dir}">
|
||||
<include name="**/**" />
|
||||
<exclude name="logs/" />
|
||||
<exclude name="doctrine-orm/package.xml" />
|
||||
</fileset>
|
||||
</tar>
|
||||
</target>
|
||||
|
||||
<target name="git-tag">
|
||||
<exec command="grep '${version}-DEV' ${project.basedir}/lib/Doctrine/ORM/Version.php" checkreturn="true"/>
|
||||
<exec command="sed 's/${version}-DEV/${version}/' ${project.basedir}/lib/Doctrine/ORM/Version.php > ${project.basedir}/lib/Doctrine/ORM/Version2.php" passthru="true" />
|
||||
<exec command="mv ${project.basedir}/lib/Doctrine/ORM/Version2.php ${project.basedir}/lib/Doctrine/ORM/Version.php" passthru="true" />
|
||||
<exec command="git add ${project.basedir}/lib/Doctrine/ORM/Version.php" passthru="true" />
|
||||
<exec command="git commit -m 'Release ${version}'" />
|
||||
<exec command="git tag -m 'Tag ${version}' -a ${version}" passthru="true" />
|
||||
</target>
|
||||
|
||||
<target name="pirum-release">
|
||||
<exec command="sudo pirum add ${project.pirum_dir} ${project.basedir}/dist/DoctrineORM-${version}.tgz" dir="." passthru="true" />
|
||||
<exec command="sudo pirum build ${project.pirum_dir}" passthru="true" />
|
||||
</target>
|
||||
|
||||
<target name="distribute-download">
|
||||
<copy file="dist/DoctrineORM-${version}-full.tar.gz" todir="${project.download_dir}" />
|
||||
<copy file="${dist.dir}/doctrine-orm-${version}.phar" todir="${project.download_dir}" />
|
||||
</target>
|
||||
|
||||
<target name="update-dev-version">
|
||||
<exec command="grep '${version}' ${project.basedir}/lib/Doctrine/ORM/Version.php" checkreturn="true"/>
|
||||
<propertyprompt propertyName="next_version" defaultValue="${version}" promptText="Enter next version string (without -DEV)" />
|
||||
<exec command="sed 's/${version}/${next_version}-DEV/' ${project.basedir}/lib/Doctrine/ORM/Version.php > ${project.basedir}/lib/Doctrine/ORM/Version2.php" passthru="true" />
|
||||
<exec command="mv ${project.basedir}/lib/Doctrine/ORM/Version2.php ${project.basedir}/lib/Doctrine/ORM/Version.php" passthru="true" />
|
||||
<exec command="git add ${project.basedir}/lib/Doctrine/ORM/Version.php" passthru="true" />
|
||||
<exec command="git commit -m 'Bump Dev Version to ${next_version}-DEV'" passthru="true" />
|
||||
</target>
|
||||
|
||||
<target name="release" depends="git-tag,build-packages,package-phar,distribute-download,pirum-release,update-dev-version" />
|
||||
|
||||
<!--
|
||||
Builds distributable PEAR packages for the Symfony Dependencies
|
||||
-->
|
||||
<target name="release-symfony-dependencies" depends="build-orm">
|
||||
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/doctrine-orm">
|
||||
<name>DoctrineSymfonyConsole</name>
|
||||
<summary>Symfony Console Component</summary>
|
||||
<channel>pear.doctrine-project.org</channel>
|
||||
<description>A command line interface tool from the Symfony project. Packaged for shipping with Doctrine projects using ORM version numbers.</description>
|
||||
<lead user="fabpot" name="Fabien Potencier" email="fabien.potencier@symfony-project.com" />
|
||||
<license>NewBSD License</license>
|
||||
<version release="${version}" api="${version}" />
|
||||
<stability release="${stability}" api="${stability}" />
|
||||
<notes>-</notes>
|
||||
<dependencies>
|
||||
<php minimum_version="5.3.0" />
|
||||
<pear minimum_version="1.6.0" recommended_version="1.6.1" />
|
||||
</dependencies>
|
||||
<ignore>bin/</ignore>
|
||||
<ignore>Doctrine/Common/</ignore>
|
||||
<ignore>Doctrine/DBAL/</ignore>
|
||||
<ignore>Doctrine/ORM/</ignore>
|
||||
<ignore>Symfony/Component/Yaml/</ignore>
|
||||
</d51pearpkg2>
|
||||
<exec command="pear package" dir="${build.dir}/doctrine-orm" passthru="true" />
|
||||
<exec command="mv DoctrineSymfonyConsole-${version}.tgz ../../dist" dir="${build.dir}/doctrine-orm" passthru="true" />
|
||||
|
||||
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/doctrine-orm">
|
||||
<name>DoctrineSymfonyYaml</name>
|
||||
<summary>Symfony Yaml Component</summary>
|
||||
<channel>pear.doctrine-project.org</channel>
|
||||
<description>A YAML Parser from the Symfony project. Packaged for shipping with Doctrine projects using ORM version numbers.</description>
|
||||
<lead user="fabpot" name="Fabien Potencier" email="fabien.potencier@symfony-project.com" />
|
||||
<license>NewBSD License</license>
|
||||
<version release="${version}" api="${version}" />
|
||||
<stability release="${stability}" api="${stability}" />
|
||||
<notes>-</notes>
|
||||
<dependencies>
|
||||
<php minimum_version="5.3.0" />
|
||||
<pear minimum_version="1.6.0" recommended_version="1.6.1" />
|
||||
</dependencies>
|
||||
<ignore>bin/</ignore>
|
||||
<ignore>Doctrine/Common/</ignore>
|
||||
<ignore>Doctrine/DBAL/</ignore>
|
||||
<ignore>Doctrine/ORM/</ignore>
|
||||
<ignore>Symfony/Component/Console/</ignore>
|
||||
</d51pearpkg2>
|
||||
<exec command="pear package" dir="${build.dir}/doctrine-orm" passthru="true" />
|
||||
<exec command="mv DoctrineSymfonyYaml-${version}.tgz ../../dist" dir="${build.dir}/doctrine-orm" passthru="true" />
|
||||
|
||||
<exec command="sudo pirum add ${project.pirum_dir} ${project.basedir}/dist/DoctrineSymfonyConsole-${version}.tgz" dir="." passthru="true" />
|
||||
<exec command="sudo pirum add ${project.pirum_dir} ${project.basedir}/dist/DoctrineSymfonyYaml-${version}.tgz" dir="." passthru="true" />
|
||||
<exec command="sudo pirum build ${project.pirum_dir}" passthru="true" />
|
||||
</target>
|
||||
</project>
|
||||
|
||||
|
||||
23
composer.json
Normal file
23
composer.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "doctrine/orm",
|
||||
"type": "library","version":"2.1.6",
|
||||
"description": "Object-Relational-Mapper for PHP",
|
||||
"keywords": ["orm", "database"],
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"license": "LGPL",
|
||||
"authors": [
|
||||
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
|
||||
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
|
||||
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
|
||||
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"ext-pdo": "*",
|
||||
"doctrine/common": "2.1.*",
|
||||
"doctrine/dbal": "2.1.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Doctrine\\ORM": "lib/" }
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ abstract class AbstractQuery
|
||||
protected $_resultSetMapping;
|
||||
|
||||
/**
|
||||
* @var Doctrine\ORM\EntityManager The entity manager used by this query object.
|
||||
* @var \Doctrine\ORM\EntityManager The entity manager used by this query object.
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
@@ -122,7 +122,7 @@ abstract class AbstractQuery
|
||||
/**
|
||||
* Initializes a new instance of a class derived from <tt>AbstractQuery</tt>.
|
||||
*
|
||||
* @param Doctrine\ORM\EntityManager $entityManager
|
||||
* @param \Doctrine\ORM\EntityManager $entityManager
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
@@ -132,7 +132,7 @@ abstract class AbstractQuery
|
||||
/**
|
||||
* Retrieves the associated EntityManager of this Query instance.
|
||||
*
|
||||
* @return Doctrine\ORM\EntityManager
|
||||
* @return \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
@@ -212,7 +212,7 @@ abstract class AbstractQuery
|
||||
* @param string $type The parameter type. If specified, the given value will be run through
|
||||
* the type conversion of this type. This is usually not needed for
|
||||
* strings and numeric types.
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function setParameter($key, $value, $type = null)
|
||||
{
|
||||
@@ -231,7 +231,7 @@ abstract class AbstractQuery
|
||||
*
|
||||
* @param array $params
|
||||
* @param array $types
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function setParameters(array $params, array $types = array())
|
||||
{
|
||||
@@ -249,7 +249,7 @@ abstract class AbstractQuery
|
||||
* Sets the ResultSetMapping that should be used for hydration.
|
||||
*
|
||||
* @param ResultSetMapping $rsm
|
||||
* @return Doctrine\ORM\AbstractQuery
|
||||
* @return \Doctrine\ORM\AbstractQuery
|
||||
*/
|
||||
public function setResultSetMapping(Query\ResultSetMapping $rsm)
|
||||
{
|
||||
@@ -260,8 +260,8 @@ abstract class AbstractQuery
|
||||
/**
|
||||
* Defines a cache driver to be used for caching result sets.
|
||||
*
|
||||
* @param Doctrine\Common\Cache\Cache $driver Cache driver
|
||||
* @return Doctrine\ORM\AbstractQuery
|
||||
* @param \Doctrine\Common\Cache\Cache $driver Cache driver
|
||||
* @return \Doctrine\ORM\AbstractQuery
|
||||
*/
|
||||
public function setResultCacheDriver($resultCacheDriver = null)
|
||||
{
|
||||
@@ -278,7 +278,7 @@ abstract class AbstractQuery
|
||||
/**
|
||||
* Returns the cache driver used for caching result sets.
|
||||
*
|
||||
* @return Doctrine\Common\Cache\Cache Cache driver
|
||||
* @return \Doctrine\Common\Cache\Cache Cache driver
|
||||
*/
|
||||
public function getResultCacheDriver()
|
||||
{
|
||||
@@ -296,7 +296,7 @@ abstract class AbstractQuery
|
||||
* @param boolean $bool
|
||||
* @param integer $timeToLive
|
||||
* @param string $resultCacheId
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function useResultCache($bool, $timeToLive = null, $resultCacheId = null)
|
||||
{
|
||||
@@ -314,7 +314,7 @@ abstract class AbstractQuery
|
||||
* Defines how long the result cache will be active before expire.
|
||||
*
|
||||
* @param integer $timeToLive How long the cache entry is valid.
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function setResultCacheLifetime($timeToLive)
|
||||
{
|
||||
@@ -340,7 +340,7 @@ abstract class AbstractQuery
|
||||
* Defines if the result cache is active or not.
|
||||
*
|
||||
* @param boolean $expire Whether or not to force resultset cache expiration.
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function expireResultCache($expire = true)
|
||||
{
|
||||
@@ -383,7 +383,7 @@ abstract class AbstractQuery
|
||||
*
|
||||
* @param integer $hydrationMode Doctrine processing mode to be used during hydration process.
|
||||
* One of the Query::HYDRATE_* constants.
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function setHydrationMode($hydrationMode)
|
||||
{
|
||||
@@ -511,7 +511,7 @@ abstract class AbstractQuery
|
||||
*
|
||||
* @param string $name The name of the hint.
|
||||
* @param mixed $value The value of the hint.
|
||||
* @return Doctrine\ORM\AbstractQuery
|
||||
* @return \Doctrine\ORM\AbstractQuery
|
||||
*/
|
||||
public function setHint($name, $value)
|
||||
{
|
||||
@@ -621,7 +621,7 @@ abstract class AbstractQuery
|
||||
* generated for you.
|
||||
*
|
||||
* @param string $id
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function setResultCacheId($id)
|
||||
{
|
||||
@@ -667,7 +667,7 @@ abstract class AbstractQuery
|
||||
/**
|
||||
* Executes the query and returns a the resulting Statement object.
|
||||
*
|
||||
* @return Doctrine\DBAL\Driver\Statement The executed database statement that holds the results.
|
||||
* @return \Doctrine\DBAL\Driver\Statement The executed database statement that holds the results.
|
||||
*/
|
||||
abstract protected function _doExecute();
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ use Doctrine\Common\Cache\Cache,
|
||||
Doctrine\Common\Cache\ArrayCache,
|
||||
Doctrine\Common\Annotations\AnnotationRegistry,
|
||||
Doctrine\Common\Annotations\AnnotationReader,
|
||||
Doctrine\Common\Annotations\SimpleAnnotationReader,
|
||||
Doctrine\ORM\Mapping\Driver\Driver,
|
||||
Doctrine\ORM\Mapping\Driver\AnnotationDriver;
|
||||
|
||||
@@ -85,7 +86,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
/**
|
||||
* Gets the namespace where proxy classes reside.
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getProxyNamespace()
|
||||
@@ -96,7 +97,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
/**
|
||||
* Sets the namespace where proxy classes reside.
|
||||
*
|
||||
*
|
||||
* @param string $ns
|
||||
*/
|
||||
public function setProxyNamespace($ns)
|
||||
@@ -118,22 +119,23 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
/**
|
||||
* Add a new default annotation driver with a correctly configured annotation reader.
|
||||
*
|
||||
*
|
||||
* @param array $paths
|
||||
* @return Mapping\Driver\AnnotationDriver
|
||||
*/
|
||||
public function newDefaultAnnotationDriver($paths = array())
|
||||
{
|
||||
if (version_compare(\Doctrine\Common\Version::VERSION, '3.0.0-DEV', '>=')) {
|
||||
if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
|
||||
// Register the ORM Annotations in the AnnotationRegistry
|
||||
AnnotationRegistry::registerFile(__DIR__ . '/Mapping/Driver/DoctrineAnnotations.php');
|
||||
|
||||
$reader = new AnnotationReader();
|
||||
|
||||
$reader = new SimpleAnnotationReader();
|
||||
$reader->addNamespace('Doctrine\ORM\Mapping');
|
||||
$reader = new \Doctrine\Common\Annotations\CachedReader($reader, new ArrayCache());
|
||||
} else if (version_compare(\Doctrine\Common\Version::VERSION, '2.1.0-DEV', '>=')) {
|
||||
// Register the ORM Annotations in the AnnotationRegistry
|
||||
AnnotationRegistry::registerFile(__DIR__ . '/Mapping/Driver/DoctrineAnnotations.php');
|
||||
|
||||
|
||||
$reader = new AnnotationReader();
|
||||
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
|
||||
$reader->setIgnoreNotImportedAnnotations(true);
|
||||
@@ -162,7 +164,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
/**
|
||||
* Resolves a registered namespace alias to the full namespace.
|
||||
*
|
||||
* @param string $entityNamespaceAlias
|
||||
* @param string $entityNamespaceAlias
|
||||
* @return string
|
||||
* @throws MappingException
|
||||
*/
|
||||
@@ -185,10 +187,10 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
{
|
||||
$this->_attributes['entityNamespaces'] = $entityNamespaces;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the list of registered entity namespace aliases.
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEntityNamespaces()
|
||||
@@ -360,7 +362,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
/**
|
||||
* Gets the implementation class name of a registered custom string DQL function.
|
||||
*
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
@@ -403,7 +405,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
/**
|
||||
* Gets the implementation class name of a registered custom numeric DQL function.
|
||||
*
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
@@ -446,7 +448,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
/**
|
||||
* Gets the implementation class name of a registered custom date/time DQL function.
|
||||
*
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
@@ -497,7 +499,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
/**
|
||||
* Set a class metadata factory.
|
||||
*
|
||||
*
|
||||
* @param string $cmf
|
||||
*/
|
||||
public function setClassMetadataFactoryName($cmfName)
|
||||
|
||||
@@ -43,21 +43,21 @@ class EntityManager implements ObjectManager
|
||||
/**
|
||||
* The used Configuration.
|
||||
*
|
||||
* @var Doctrine\ORM\Configuration
|
||||
* @var \Doctrine\ORM\Configuration
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* The database connection used by the EntityManager.
|
||||
*
|
||||
* @var Doctrine\DBAL\Connection
|
||||
* @var \Doctrine\DBAL\Connection
|
||||
*/
|
||||
private $conn;
|
||||
|
||||
/**
|
||||
* The metadata factory, used to retrieve the ORM metadata of entity classes.
|
||||
*
|
||||
* @var Doctrine\ORM\Mapping\ClassMetadataFactory
|
||||
* @var \Doctrine\ORM\Mapping\ClassMetadataFactory
|
||||
*/
|
||||
private $metadataFactory;
|
||||
|
||||
@@ -71,14 +71,14 @@ class EntityManager implements ObjectManager
|
||||
/**
|
||||
* The UnitOfWork used to coordinate object-level transactions.
|
||||
*
|
||||
* @var Doctrine\ORM\UnitOfWork
|
||||
* @var \Doctrine\ORM\UnitOfWork
|
||||
*/
|
||||
private $unitOfWork;
|
||||
|
||||
/**
|
||||
* The event manager that is the central point of the event system.
|
||||
*
|
||||
* @var Doctrine\Common\EventManager
|
||||
* @var \Doctrine\Common\EventManager
|
||||
*/
|
||||
private $eventManager;
|
||||
|
||||
@@ -92,14 +92,14 @@ class EntityManager implements ObjectManager
|
||||
/**
|
||||
* The proxy factory used to create dynamic proxies.
|
||||
*
|
||||
* @var Doctrine\ORM\Proxy\ProxyFactory
|
||||
* @var \Doctrine\ORM\Proxy\ProxyFactory
|
||||
*/
|
||||
private $proxyFactory;
|
||||
|
||||
/**
|
||||
* The expression builder instance used to generate query expressions.
|
||||
*
|
||||
* @var Doctrine\ORM\Query\Expr
|
||||
* @var \Doctrine\ORM\Query\Expr
|
||||
*/
|
||||
private $expressionBuilder;
|
||||
|
||||
@@ -114,9 +114,9 @@ class EntityManager implements ObjectManager
|
||||
* Creates a new EntityManager that operates on the given database connection
|
||||
* and uses the given Configuration and EventManager implementations.
|
||||
*
|
||||
* @param Doctrine\DBAL\Connection $conn
|
||||
* @param Doctrine\ORM\Configuration $config
|
||||
* @param Doctrine\Common\EventManager $eventManager
|
||||
* @param \Doctrine\DBAL\Connection $conn
|
||||
* @param \Doctrine\ORM\Configuration $config
|
||||
* @param \Doctrine\Common\EventManager $eventManager
|
||||
*/
|
||||
protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager)
|
||||
{
|
||||
@@ -128,7 +128,7 @@ class EntityManager implements ObjectManager
|
||||
$this->metadataFactory = new $metadataFactoryClassName;
|
||||
$this->metadataFactory->setEntityManager($this);
|
||||
$this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl());
|
||||
|
||||
|
||||
$this->unitOfWork = new UnitOfWork($this);
|
||||
$this->proxyFactory = new ProxyFactory($this,
|
||||
$config->getProxyDir(),
|
||||
@@ -139,7 +139,7 @@ class EntityManager implements ObjectManager
|
||||
/**
|
||||
* Gets the database connection object used by the EntityManager.
|
||||
*
|
||||
* @return Doctrine\DBAL\Connection
|
||||
* @return \Doctrine\DBAL\Connection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
@@ -149,7 +149,7 @@ class EntityManager implements ObjectManager
|
||||
/**
|
||||
* Gets the metadata factory used to gather the metadata of classes.
|
||||
*
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadataFactory
|
||||
* @return \Doctrine\ORM\Mapping\ClassMetadataFactory
|
||||
*/
|
||||
public function getMetadataFactory()
|
||||
{
|
||||
@@ -168,7 +168,7 @@ class EntityManager implements ObjectManager
|
||||
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
|
||||
* </code>
|
||||
*
|
||||
* @return Doctrine\ORM\Query\Expr
|
||||
* @return \Doctrine\ORM\Query\Expr
|
||||
*/
|
||||
public function getExpressionBuilder()
|
||||
{
|
||||
@@ -203,18 +203,18 @@ class EntityManager implements ObjectManager
|
||||
public function transactional(Closure $func)
|
||||
{
|
||||
$this->conn->beginTransaction();
|
||||
|
||||
|
||||
try {
|
||||
$return = $func($this);
|
||||
|
||||
|
||||
$this->flush();
|
||||
$this->conn->commit();
|
||||
|
||||
|
||||
return $return ?: true;
|
||||
} catch (Exception $e) {
|
||||
$this->close();
|
||||
$this->conn->rollback();
|
||||
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
@@ -244,12 +244,12 @@ class EntityManager implements ObjectManager
|
||||
*
|
||||
* The class name must be the fully-qualified class name without a leading backslash
|
||||
* (as it is returned by get_class($obj)) or an aliased class name.
|
||||
*
|
||||
*
|
||||
* Examples:
|
||||
* MyProject\Domain\User
|
||||
* sales:PriceRequest
|
||||
*
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @return \Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @internal Performance-sensitive method.
|
||||
*/
|
||||
public function getClassMetadata($className)
|
||||
@@ -261,7 +261,7 @@ class EntityManager implements ObjectManager
|
||||
* Creates a new Query object.
|
||||
*
|
||||
* @param string The DQL string.
|
||||
* @return Doctrine\ORM\Query
|
||||
* @return \Doctrine\ORM\Query
|
||||
*/
|
||||
public function createQuery($dql = "")
|
||||
{
|
||||
@@ -276,7 +276,7 @@ class EntityManager implements ObjectManager
|
||||
* Creates a Query from a named query.
|
||||
*
|
||||
* @param string $name
|
||||
* @return Doctrine\ORM\Query
|
||||
* @return \Doctrine\ORM\Query
|
||||
*/
|
||||
public function createNamedQuery($name)
|
||||
{
|
||||
@@ -302,7 +302,7 @@ class EntityManager implements ObjectManager
|
||||
* Creates a NativeQuery from a named native query.
|
||||
*
|
||||
* @param string $name
|
||||
* @return Doctrine\ORM\NativeQuery
|
||||
* @return \Doctrine\ORM\NativeQuery
|
||||
*/
|
||||
public function createNamedNativeQuery($name)
|
||||
{
|
||||
@@ -325,7 +325,7 @@ class EntityManager implements ObjectManager
|
||||
* This effectively synchronizes the in-memory state of managed objects with the
|
||||
* database.
|
||||
*
|
||||
* @throws Doctrine\ORM\OptimisticLockException If a version check on an entity that
|
||||
* @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that
|
||||
* makes use of optimistic locking fails.
|
||||
*/
|
||||
public function flush()
|
||||
@@ -413,6 +413,7 @@ class EntityManager implements ObjectManager
|
||||
$entity = $class->newInstance();
|
||||
$class->setIdentifierValues($entity, $identifier);
|
||||
$this->unitOfWork->registerManaged($entity, $identifier, array());
|
||||
$this->unitOfWork->markReadOnly($entity);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
@@ -449,7 +450,7 @@ class EntityManager implements ObjectManager
|
||||
*
|
||||
* The entity will be entered into the database at or before transaction
|
||||
* commit or as a result of the flush operation.
|
||||
*
|
||||
*
|
||||
* NOTE: The persist operation always considers entities that are not yet known to
|
||||
* this EntityManager as NEW. Do not pass detached entities to the persist operation.
|
||||
*
|
||||
@@ -600,7 +601,7 @@ class EntityManager implements ObjectManager
|
||||
/**
|
||||
* Gets the EventManager used by the EntityManager.
|
||||
*
|
||||
* @return Doctrine\Common\EventManager
|
||||
* @return \Doctrine\Common\EventManager
|
||||
*/
|
||||
public function getEventManager()
|
||||
{
|
||||
@@ -610,7 +611,7 @@ class EntityManager implements ObjectManager
|
||||
/**
|
||||
* Gets the Configuration used by the EntityManager.
|
||||
*
|
||||
* @return Doctrine\ORM\Configuration
|
||||
* @return \Doctrine\ORM\Configuration
|
||||
*/
|
||||
public function getConfiguration()
|
||||
{
|
||||
@@ -631,7 +632,7 @@ class EntityManager implements ObjectManager
|
||||
|
||||
/**
|
||||
* Check if the Entity manager is open or closed.
|
||||
*
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isOpen()
|
||||
@@ -642,7 +643,7 @@ class EntityManager implements ObjectManager
|
||||
/**
|
||||
* Gets the UnitOfWork used by the EntityManager to coordinate operations.
|
||||
*
|
||||
* @return Doctrine\ORM\UnitOfWork
|
||||
* @return \Doctrine\ORM\UnitOfWork
|
||||
*/
|
||||
public function getUnitOfWork()
|
||||
{
|
||||
@@ -656,7 +657,7 @@ class EntityManager implements ObjectManager
|
||||
* selectively iterate over the result.
|
||||
*
|
||||
* @param int $hydrationMode
|
||||
* @return Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
*/
|
||||
public function getHydrator($hydrationMode)
|
||||
{
|
||||
@@ -671,7 +672,7 @@ class EntityManager implements ObjectManager
|
||||
* Create a new instance for the given hydration mode.
|
||||
*
|
||||
* @param int $hydrationMode
|
||||
* @return Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
*/
|
||||
public function newHydrator($hydrationMode)
|
||||
{
|
||||
@@ -712,6 +713,14 @@ class EntityManager implements ObjectManager
|
||||
return $this->proxyFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function initializeObject($entity)
|
||||
{
|
||||
$this->unitOfWork->initializeObject($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create EntityManager instances.
|
||||
*
|
||||
|
||||
@@ -48,7 +48,7 @@ class EntityRepository implements ObjectRepository
|
||||
protected $_em;
|
||||
|
||||
/**
|
||||
* @var Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @var \Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
protected $_class;
|
||||
|
||||
@@ -112,7 +112,7 @@ class EntityRepository implements ObjectRepository
|
||||
if (!($entity instanceof $this->_class->name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if ($lockMode != LockMode::NONE) {
|
||||
$this->_em->lock($entity, $lockMode, $lockVersion);
|
||||
}
|
||||
@@ -141,7 +141,7 @@ class EntityRepository implements ObjectRepository
|
||||
if (!$this->_em->getConnection()->isTransactionActive()) {
|
||||
throw TransactionRequiredException::transactionRequired();
|
||||
}
|
||||
|
||||
|
||||
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id, null, null, array(), $lockMode);
|
||||
}
|
||||
}
|
||||
@@ -241,4 +241,4 @@ class EntityRepository implements ObjectRepository
|
||||
{
|
||||
return $this->_class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ abstract class AbstractIdGenerator
|
||||
/**
|
||||
* Generates an identifier for an entity.
|
||||
*
|
||||
* @param Doctrine\ORM\Entity $entity
|
||||
* @param \Doctrine\ORM\Entity $entity
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function generate(EntityManager $em, $entity);
|
||||
|
||||
@@ -37,7 +37,7 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
|
||||
/**
|
||||
* Initializes a new sequence generator.
|
||||
*
|
||||
* @param Doctrine\ORM\EntityManager $em The EntityManager to use.
|
||||
* @param \Doctrine\ORM\EntityManager $em The EntityManager to use.
|
||||
* @param string $sequenceName The name of the sequence.
|
||||
* @param integer $allocationSize The allocation size of the sequence.
|
||||
*/
|
||||
|
||||
@@ -58,7 +58,7 @@ abstract class AbstractHydrator
|
||||
/**
|
||||
* Initializes a new instance of a class derived from <tt>AbstractHydrator</tt>.
|
||||
*
|
||||
* @param Doctrine\ORM\EntityManager $em The EntityManager to use.
|
||||
* @param \Doctrine\ORM\EntityManager $em The EntityManager to use.
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
@@ -164,6 +164,11 @@ abstract class AbstractHydrator
|
||||
* field names during this procedure as well as any necessary conversions on
|
||||
* the values applied.
|
||||
*
|
||||
* @param array $data SQL Result Row
|
||||
* @param array &$cache Cache for column to field result information
|
||||
* @param array &$id Dql-Alias => ID-Hash
|
||||
* @param array &$nonemptyComponents Does this DQL-Alias has at least one non NULL value?
|
||||
*
|
||||
* @return array An array with all the fields (name => value) of the data row,
|
||||
* grouped by their component alias.
|
||||
*/
|
||||
@@ -211,8 +216,11 @@ abstract class AbstractHydrator
|
||||
}
|
||||
|
||||
if (isset($cache[$key]['isMetaColumn'])) {
|
||||
if (!isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) || $value !== null) {
|
||||
if ( ! isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) && $value !== null) {
|
||||
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $value;
|
||||
if ($cache[$key]['isIdentifier']) {
|
||||
$nonemptyComponents[$dqlAlias] = true;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -92,6 +92,11 @@ class ArrayHydrator extends AbstractHydrator
|
||||
$parent = $this->_rsm->parentAliasMap[$dqlAlias];
|
||||
$path = $parent . '.' . $dqlAlias;
|
||||
|
||||
// missing parent data, skipping as RIGHT JOIN hydration is not supported.
|
||||
if ( ! isset($nonemptyComponents[$parent]) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get a reference to the right element in the result tree.
|
||||
// This element will get the associated element attached.
|
||||
if ($this->_rsm->isMixed && isset($this->_rootAliases[$parent])) {
|
||||
@@ -154,6 +159,17 @@ class ArrayHydrator extends AbstractHydrator
|
||||
// It's a root result element
|
||||
|
||||
$this->_rootAliases[$dqlAlias] = true; // Mark as root
|
||||
|
||||
// if this row has a NULL value for the root result id then make it a null result.
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) ) {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array(0 => null);
|
||||
} else {
|
||||
$result[] = null;
|
||||
}
|
||||
++$this->_resultCounter;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for an existing element
|
||||
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Doctrine\ORM\Internal\Hydration;
|
||||
class IterableResult implements \Iterator
|
||||
{
|
||||
/**
|
||||
* @var Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
* @var \Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
*/
|
||||
private $_hydrator;
|
||||
|
||||
@@ -49,7 +49,7 @@ class IterableResult implements \Iterator
|
||||
private $_current = null;
|
||||
|
||||
/**
|
||||
* @param Doctrine\ORM\Internal\Hydration\AbstractHydrator $hydrator
|
||||
* @param \Doctrine\ORM\Internal\Hydration\AbstractHydrator $hydrator
|
||||
*/
|
||||
public function __construct($hydrator)
|
||||
{
|
||||
|
||||
@@ -24,7 +24,8 @@ use PDO,
|
||||
Doctrine\ORM\PersistentCollection,
|
||||
Doctrine\ORM\Query,
|
||||
Doctrine\Common\Collections\ArrayCollection,
|
||||
Doctrine\Common\Collections\Collection;
|
||||
Doctrine\Common\Collections\Collection,
|
||||
Doctrine\ORM\Proxy\Proxy;
|
||||
|
||||
/**
|
||||
* The ObjectHydrator constructs an object graph out of an SQL result set.
|
||||
@@ -62,7 +63,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
if (!isset($this->_hints['deferEagerLoad'])) {
|
||||
$this->_hints['deferEagerLoad'] = true;
|
||||
}
|
||||
|
||||
|
||||
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
|
||||
$this->_identifierMap[$dqlAlias] = array();
|
||||
$this->_idTemplate[$dqlAlias] = '';
|
||||
@@ -82,26 +83,18 @@ class ObjectHydrator extends AbstractHydrator
|
||||
$sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
|
||||
$sourceClass = $this->_getClassMetadata($sourceClassName);
|
||||
$assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
|
||||
$this->_hints['fetched'][$sourceClassName][$assoc['fieldName']] = true;
|
||||
if ($sourceClass->subClasses) {
|
||||
foreach ($sourceClass->subClasses as $sourceSubclassName) {
|
||||
$this->_hints['fetched'][$sourceSubclassName][$assoc['fieldName']] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_hints['fetched'][$this->_rsm->parentAliasMap[$dqlAlias]][$assoc['fieldName']] = true;
|
||||
|
||||
if ($assoc['type'] != ClassMetadata::MANY_TO_MANY) {
|
||||
// Mark any non-collection opposite sides as fetched, too.
|
||||
if ($assoc['mappedBy']) {
|
||||
$this->_hints['fetched'][$className][$assoc['mappedBy']] = true;
|
||||
$this->_hints['fetched'][$dqlAlias][$assoc['mappedBy']] = true;
|
||||
} else {
|
||||
if ($assoc['inversedBy']) {
|
||||
$inverseAssoc = $class->associationMappings[$assoc['inversedBy']];
|
||||
if ($inverseAssoc['type'] & ClassMetadata::TO_ONE) {
|
||||
$this->_hints['fetched'][$className][$inverseAssoc['fieldName']] = true;
|
||||
if ($class->subClasses) {
|
||||
foreach ($class->subClasses as $targetSubclassName) {
|
||||
$this->_hints['fetched'][$targetSubclassName][$inverseAssoc['fieldName']] = true;
|
||||
}
|
||||
}
|
||||
$this->_hints['fetched'][$dqlAlias][$inverseAssoc['fieldName']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,13 +109,13 @@ class ObjectHydrator extends AbstractHydrator
|
||||
protected function _cleanup()
|
||||
{
|
||||
$eagerLoad = (isset($this->_hints['deferEagerLoad'])) && $this->_hints['deferEagerLoad'] == true;
|
||||
|
||||
|
||||
parent::_cleanup();
|
||||
$this->_identifierMap =
|
||||
$this->_initializedCollections =
|
||||
$this->_existingCollections =
|
||||
$this->_resultPointers = array();
|
||||
|
||||
|
||||
if ($eagerLoad) {
|
||||
$this->_em->getUnitOfWork()->triggerEagerLoads();
|
||||
}
|
||||
@@ -154,7 +147,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
* @param object $entity The entity to which the collection belongs.
|
||||
* @param string $name The name of the field on the entity that holds the collection.
|
||||
*/
|
||||
private function _initRelatedCollection($entity, $class, $fieldName)
|
||||
private function _initRelatedCollection($entity, $class, $fieldName, $parentDqlAlias)
|
||||
{
|
||||
$oid = spl_object_hash($entity);
|
||||
$relation = $class->associationMappings[$fieldName];
|
||||
@@ -175,7 +168,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
$this->_uow->setOriginalEntityProperty($oid, $fieldName, $value);
|
||||
$this->_initializedCollections[$oid . $fieldName] = $value;
|
||||
} else if (isset($this->_hints[Query::HINT_REFRESH]) ||
|
||||
isset($this->_hints['fetched'][$class->name][$fieldName]) &&
|
||||
isset($this->_hints['fetched'][$parentDqlAlias][$fieldName]) &&
|
||||
! $value->isInitialized()) {
|
||||
// Is already PersistentCollection, but either REFRESH or FETCH-JOIN and UNINITIALIZED!
|
||||
$value->setDirty(false);
|
||||
@@ -192,7 +185,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
|
||||
/**
|
||||
* Gets an entity instance.
|
||||
*
|
||||
*
|
||||
* @param $data The instance data.
|
||||
* @param $dqlAlias The DQL alias of the entity's class.
|
||||
* @return object The entity.
|
||||
@@ -205,12 +198,13 @@ class ObjectHydrator extends AbstractHydrator
|
||||
$className = $this->_ce[$className]->discriminatorMap[$data[$discrColumn]];
|
||||
unset($data[$discrColumn]);
|
||||
}
|
||||
|
||||
|
||||
if (isset($this->_hints[Query::HINT_REFRESH_ENTITY]) && isset($this->_rootAliases[$dqlAlias])) {
|
||||
$class = $this->_ce[$className];
|
||||
$this->registerManaged($class, $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
|
||||
}
|
||||
|
||||
|
||||
$this->_hints['fetchAlias'] = $dqlAlias;
|
||||
return $this->_uow->createEntity($className, $data, $this->_hints);
|
||||
}
|
||||
|
||||
@@ -240,7 +234,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
* Gets a ClassMetadata instance from the local cache.
|
||||
* If the instance is not yet in the local cache, it is loaded into the
|
||||
* local cache.
|
||||
*
|
||||
*
|
||||
* @param string $className The name of the class.
|
||||
* @return ClassMetadata
|
||||
*/
|
||||
@@ -254,21 +248,21 @@ class ObjectHydrator extends AbstractHydrator
|
||||
|
||||
/**
|
||||
* Hydrates a single row in an SQL result set.
|
||||
*
|
||||
*
|
||||
* @internal
|
||||
* First, the data of the row is split into chunks where each chunk contains data
|
||||
* that belongs to a particular component/class. Afterwards, all these chunks
|
||||
* are processed, one after the other. For each chunk of class data only one of the
|
||||
* following code paths is executed:
|
||||
*
|
||||
*
|
||||
* Path A: The data chunk belongs to a joined/associated object and the association
|
||||
* is collection-valued.
|
||||
* Path B: The data chunk belongs to a joined/associated object and the association
|
||||
* is single-valued.
|
||||
* Path C: The data chunk belongs to a root result element/object that appears in the topmost
|
||||
* level of the hydrated result. A typical example are the objects of the type
|
||||
* specified by the FROM clause in a DQL query.
|
||||
*
|
||||
* specified by the FROM clause in a DQL query.
|
||||
*
|
||||
* @param array $data The data of the row to process.
|
||||
* @param array $cache The cache to use.
|
||||
* @param array $result The result array to fill.
|
||||
@@ -302,10 +296,16 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// seen for this parent-child relationship
|
||||
$path = $parentAlias . '.' . $dqlAlias;
|
||||
|
||||
// We have a RIGHT JOIN result here. Doctrine cannot hydrate RIGHT JOIN Object-Graphs
|
||||
if (!isset($nonemptyComponents[$parentAlias])) {
|
||||
// TODO: Add special case code where we hydrate the right join objects into identity map at least
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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 = $this->_resultPointers[$parentAlias][key($first)];
|
||||
$parentObject = $first[key($first)];
|
||||
} else if (isset($this->_resultPointers[$parentAlias])) {
|
||||
$parentObject = $this->_resultPointers[$parentAlias];
|
||||
} else {
|
||||
@@ -321,13 +321,14 @@ class ObjectHydrator extends AbstractHydrator
|
||||
|
||||
// Check the type of the relation (many or single-valued)
|
||||
if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) {
|
||||
$reflFieldValue = $reflField->getValue($parentObject);
|
||||
// PATH A: Collection-valued association
|
||||
if (isset($nonemptyComponents[$dqlAlias])) {
|
||||
$collKey = $oid . $relationField;
|
||||
if (isset($this->_initializedCollections[$collKey])) {
|
||||
$reflFieldValue = $this->_initializedCollections[$collKey];
|
||||
} else if ( ! isset($this->_existingCollections[$collKey])) {
|
||||
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField);
|
||||
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias);
|
||||
}
|
||||
|
||||
$indexExists = isset($this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]]);
|
||||
@@ -362,16 +363,18 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// Update result pointer
|
||||
$this->_resultPointers[$dqlAlias] = $reflFieldValue[$index];
|
||||
}
|
||||
} else if ( ! $reflField->getValue($parentObject)) {
|
||||
$coll = new PersistentCollection($this->_em, $this->_ce[$entityName], new ArrayCollection);
|
||||
$coll->setOwner($parentObject, $relation);
|
||||
$reflField->setValue($parentObject, $coll);
|
||||
$this->_uow->setOriginalEntityProperty($oid, $relationField, $coll);
|
||||
} else if ( ! $reflFieldValue) {
|
||||
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias);
|
||||
} else if ($reflFieldValue instanceof PersistentCollection && $reflFieldValue->isInitialized() === false) {
|
||||
$reflFieldValue->setInitialized(true);
|
||||
}
|
||||
|
||||
} else {
|
||||
// PATH B: Single-valued association
|
||||
$reflFieldValue = $reflField->getValue($parentObject);
|
||||
if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH])) {
|
||||
if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH]) || ($reflFieldValue instanceof Proxy && !$reflFieldValue->__isInitialized__)) {
|
||||
// we only need to take action if this value is null,
|
||||
// we refresh the entity or its an unitialized proxy.
|
||||
if (isset($nonemptyComponents[$dqlAlias])) {
|
||||
$element = $this->_getEntity($data, $dqlAlias);
|
||||
$reflField->setValue($parentObject, $element);
|
||||
@@ -397,6 +400,8 @@ class ObjectHydrator extends AbstractHydrator
|
||||
}
|
||||
// Update result pointer
|
||||
$this->_resultPointers[$dqlAlias] = $element;
|
||||
} else {
|
||||
$this->_uow->setOriginalEntityProperty($oid, $relationField, null);
|
||||
}
|
||||
// else leave $reflFieldValue null for single-valued associations
|
||||
} else {
|
||||
@@ -408,6 +413,18 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// PATH C: Its a root result element
|
||||
$this->_rootAliases[$dqlAlias] = true; // Mark as root alias
|
||||
|
||||
// if this row has a NULL value for the root result id then make it a null result.
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) ) {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array(0 => null);
|
||||
} else {
|
||||
$result[] = null;
|
||||
}
|
||||
++$this->_resultCounter;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for existing result from the iterations before
|
||||
if ( ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $this->_getEntity($rowData[$dqlAlias], $dqlAlias);
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
|
||||
@@ -43,7 +43,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $em;
|
||||
|
||||
|
||||
/**
|
||||
* @var AbstractPlatform
|
||||
*/
|
||||
@@ -73,7 +73,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
* @var bool
|
||||
*/
|
||||
private $initialized = false;
|
||||
|
||||
|
||||
/**
|
||||
* @param EntityManager $$em
|
||||
*/
|
||||
@@ -85,7 +85,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
/**
|
||||
* Sets the cache driver used by the factory to cache ClassMetadata instances.
|
||||
*
|
||||
* @param Doctrine\Common\Cache\Cache $cacheDriver
|
||||
* @param \Doctrine\Common\Cache\Cache $cacheDriver
|
||||
*/
|
||||
public function setCacheDriver($cacheDriver)
|
||||
{
|
||||
@@ -95,22 +95,22 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
/**
|
||||
* Gets the cache driver used by the factory to cache ClassMetadata instances.
|
||||
*
|
||||
* @return Doctrine\Common\Cache\Cache
|
||||
* @return \Doctrine\Common\Cache\Cache
|
||||
*/
|
||||
public function getCacheDriver()
|
||||
{
|
||||
return $this->cacheDriver;
|
||||
}
|
||||
|
||||
|
||||
public function getLoadedMetadata()
|
||||
{
|
||||
return $this->loadedMetadata;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Forces the factory to load the metadata of all classes known to the underlying
|
||||
* mapping driver.
|
||||
*
|
||||
*
|
||||
* @return array The ClassMetadata instances of all mapped classes.
|
||||
*/
|
||||
public function getAllMetadata()
|
||||
@@ -143,7 +143,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
* Gets the class metadata descriptor for a class.
|
||||
*
|
||||
* @param string $className The name of the class.
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @return \Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
public function getMetadataFor($className)
|
||||
{
|
||||
@@ -188,7 +188,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
|
||||
/**
|
||||
* Checks whether the factory has the metadata for a class loaded already.
|
||||
*
|
||||
*
|
||||
* @param string $className
|
||||
* @return boolean TRUE if the metadata of the class in question is already loaded, FALSE otherwise.
|
||||
*/
|
||||
@@ -199,7 +199,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
|
||||
/**
|
||||
* Sets the metadata descriptor for a specific class.
|
||||
*
|
||||
*
|
||||
* NOTE: This is only useful in very special cases, like when generating proxy classes.
|
||||
*
|
||||
* @param string $className
|
||||
@@ -306,6 +306,10 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
$class->setPrimaryTable($parent->table);
|
||||
}
|
||||
|
||||
if ($parent && $parent->containsForeignIdentifier) {
|
||||
$class->containsForeignIdentifier = true;
|
||||
}
|
||||
|
||||
$class->setParentClasses($visited);
|
||||
|
||||
if ($this->evm->hasListeners(Events::loadClassMetadata)) {
|
||||
@@ -314,7 +318,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
}
|
||||
|
||||
$this->validateRuntimeMetadata($class, $parent);
|
||||
|
||||
|
||||
$this->loadedMetadata[$className] = $class;
|
||||
|
||||
$parent = $class;
|
||||
@@ -366,7 +370,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
* Creates a new ClassMetadata instance for the given class name.
|
||||
*
|
||||
* @param string $className
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @return \Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
protected function newClassMetadataInstance($className)
|
||||
{
|
||||
@@ -376,8 +380,8 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
/**
|
||||
* Adds inherited fields to the subclass mapping.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
*/
|
||||
private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass)
|
||||
{
|
||||
@@ -398,8 +402,8 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
/**
|
||||
* Adds inherited association mappings to the subclass mapping.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
*/
|
||||
private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass)
|
||||
{
|
||||
@@ -426,7 +430,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
* Completes the ID generator mapping. If "auto" is specified we choose the generator
|
||||
* most appropriate for the targeted database platform.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
*/
|
||||
private function completeIdGeneratorMapping(ClassMetadataInfo $class)
|
||||
{
|
||||
@@ -478,4 +482,22 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
||||
throw new ORMException("Unknown generator type: " . $class->generatorType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isTransient($class)
|
||||
{
|
||||
if ( ! $this->initialized) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
// Check for namespace alias
|
||||
if (strpos($class, ':') !== false) {
|
||||
list($namespaceAlias, $simpleClassName) = explode(':', $class);
|
||||
$class = $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName;
|
||||
}
|
||||
|
||||
return $this->driver->isTransient($class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
const FETCH_LAZY = 2;
|
||||
/**
|
||||
* Specifies that an association is to be fetched when the owner of the
|
||||
* association is fetched.
|
||||
* association is fetched.
|
||||
*/
|
||||
const FETCH_EAGER = 3;
|
||||
/**
|
||||
@@ -206,7 +206,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
|
||||
/**
|
||||
* READ-ONLY: The named queries allowed to be called directly from Repository.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $namedQueries = array();
|
||||
@@ -361,7 +361,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
* - <b>mappedBy</b> (string, required for bidirectional associations)
|
||||
* The name of the field that completes the bidirectional association on the owning side.
|
||||
* This key must be specified on the inverse side of a bidirectional association.
|
||||
*
|
||||
*
|
||||
* - <b>inversedBy</b> (string, required for bidirectional associations)
|
||||
* The name of the field that completes the bidirectional association on the inverse side.
|
||||
* This key must be specified on the owning side of a bidirectional association.
|
||||
@@ -388,7 +388,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
* Specification of a field on target-entity that is used to index the collection by.
|
||||
* This field HAS to be either the primary key or a unique column. Otherwise the collection
|
||||
* does not contain all the entities that are actually related.
|
||||
*
|
||||
*
|
||||
* A join table definition has the following structure:
|
||||
* <pre>
|
||||
* array(
|
||||
@@ -430,7 +430,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
/**
|
||||
* READ-ONLY: The definition of the sequence generator of this class. Only used for the
|
||||
* SEQUENCE generation strategy.
|
||||
*
|
||||
*
|
||||
* The definition has the following structure:
|
||||
* <code>
|
||||
* array(
|
||||
@@ -774,12 +774,12 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
// If targetEntity is unqualified, assume it is in the same namespace as
|
||||
// the sourceEntity.
|
||||
$mapping['sourceEntity'] = $this->name;
|
||||
|
||||
|
||||
if (isset($mapping['targetEntity'])) {
|
||||
if (strlen($this->namespace) > 0 && strpos($mapping['targetEntity'], '\\') === false) {
|
||||
$mapping['targetEntity'] = $this->namespace . '\\' . $mapping['targetEntity'];
|
||||
}
|
||||
|
||||
|
||||
$mapping['targetEntity'] = ltrim($mapping['targetEntity'], '\\');
|
||||
}
|
||||
|
||||
@@ -813,7 +813,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
if ( ! isset($mapping['targetEntity'])) {
|
||||
throw MappingException::missingTargetEntity($mapping['fieldName']);
|
||||
}
|
||||
|
||||
|
||||
// Mandatory and optional attributes for either side
|
||||
if ( ! $mapping['mappedBy']) {
|
||||
if (isset($mapping['joinTable']) && $mapping['joinTable']) {
|
||||
@@ -829,7 +829,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
if (isset($mapping['id']) && $mapping['id'] === true && $mapping['type'] & self::TO_MANY) {
|
||||
throw MappingException::illegalToManyIdentifierAssoaction($this->name, $mapping['fieldName']);
|
||||
}
|
||||
|
||||
|
||||
// Fetch mode. Default fetch mode to LAZY, if not set.
|
||||
if ( ! isset($mapping['fetch'])) {
|
||||
$mapping['fetch'] = self::FETCH_LAZY;
|
||||
@@ -852,7 +852,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
$mapping['isCascadeRefresh'] = in_array('refresh', $cascades);
|
||||
$mapping['isCascadeMerge'] = in_array('merge', $cascades);
|
||||
$mapping['isCascadeDetach'] = in_array('detach', $cascades);
|
||||
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
@@ -866,11 +866,11 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
protected function _validateAndCompleteOneToOneMapping(array $mapping)
|
||||
{
|
||||
$mapping = $this->_validateAndCompleteAssociationMapping($mapping);
|
||||
|
||||
|
||||
if (isset($mapping['joinColumns']) && $mapping['joinColumns']) {
|
||||
$mapping['isOwningSide'] = true;
|
||||
}
|
||||
|
||||
|
||||
if ($mapping['isOwningSide']) {
|
||||
if ( ! isset($mapping['joinColumns']) || ! $mapping['joinColumns']) {
|
||||
// Apply default join column
|
||||
@@ -937,7 +937,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
if ( ! isset($mapping['mappedBy'])) {
|
||||
throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']);
|
||||
}
|
||||
|
||||
|
||||
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ? (bool) $mapping['orphanRemoval'] : false;
|
||||
$mapping['isCascadeRemove'] = $mapping['orphanRemoval'] ? true : $mapping['isCascadeRemove'];
|
||||
|
||||
@@ -946,7 +946,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
throw new \InvalidArgumentException("'orderBy' is expected to be an array, not ".gettype($mapping['orderBy']));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
@@ -964,7 +964,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
} else {
|
||||
$targetShortName = strtolower($mapping['targetEntity']);
|
||||
}
|
||||
|
||||
|
||||
// owning side MUST have a join table
|
||||
if ( ! isset($mapping['joinTable']['name'])) {
|
||||
$mapping['joinTable']['name'] = $sourceShortName .'_' . $targetShortName;
|
||||
@@ -1115,23 +1115,23 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
*/
|
||||
public function getIdentifierColumnNames()
|
||||
{
|
||||
if ($this->isIdentifierComposite) {
|
||||
$columnNames = array();
|
||||
foreach ($this->identifier as $idField) {
|
||||
if (isset($this->associationMappings[$idField])) {
|
||||
// no composite pk as fk entity assumption:
|
||||
$columnNames[] = $this->associationMappings[$idField]['joinColumns'][0]['name'];
|
||||
} else {
|
||||
$columnNames[] = $this->fieldMappings[$idField]['columnName'];
|
||||
}
|
||||
$columnNames = array();
|
||||
|
||||
foreach ($this->identifier as $idProperty) {
|
||||
if (isset($this->fieldMappings[$idProperty])) {
|
||||
$columnNames[] = $this->fieldMappings[$idProperty]['columnName'];
|
||||
|
||||
continue;
|
||||
}
|
||||
return $columnNames;
|
||||
} else if(isset($this->fieldMappings[$this->identifier[0]])) {
|
||||
return array($this->fieldMappings[$this->identifier[0]]['columnName']);
|
||||
} else {
|
||||
// no composite pk as fk entity assumption:
|
||||
return array($this->associationMappings[$this->identifier[0]]['joinColumns'][0]['name']);
|
||||
|
||||
// Association defined as Id field
|
||||
$joinColumns = $this->associationMappings[$idProperty]['joinColumns'];
|
||||
$assocColumnNames = array_map(function ($joinColumn) { return $joinColumn['name']; }, $joinColumns);
|
||||
|
||||
$columnNames = array_merge($columnNames, $assocColumnNames);
|
||||
}
|
||||
|
||||
return $columnNames;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1238,7 +1238,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
* Gets the type of a field.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return Doctrine\DBAL\Types\Type
|
||||
* @return \Doctrine\DBAL\Types\Type
|
||||
*/
|
||||
public function getTypeOfField($fieldName)
|
||||
{
|
||||
@@ -1249,7 +1249,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
/**
|
||||
* Gets the type of a column.
|
||||
*
|
||||
* @return Doctrine\DBAL\Types\Type
|
||||
* @return \Doctrine\DBAL\Types\Type
|
||||
*/
|
||||
public function getTypeOfColumn($columnName)
|
||||
{
|
||||
@@ -1630,10 +1630,10 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
if (strlen($this->namespace) > 0 && strpos($className, '\\') === false) {
|
||||
$className = $this->namespace . '\\' . $className;
|
||||
}
|
||||
|
||||
|
||||
$className = ltrim($className, '\\');
|
||||
$this->discriminatorMap[$value] = $className;
|
||||
|
||||
|
||||
if ($this->name == $className) {
|
||||
$this->discriminatorValue = $value;
|
||||
} else {
|
||||
@@ -1712,7 +1712,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
|
||||
/**
|
||||
* Return the single association join column (if any).
|
||||
*
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return string
|
||||
*/
|
||||
@@ -1754,7 +1754,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
foreach ($this->associationMappings AS $assocName => $mapping) {
|
||||
if ($this->isAssociationWithSingleJoinColumn($assocName) &&
|
||||
$this->associationMappings[$assocName]['joinColumns'][0]['name'] == $columnName) {
|
||||
|
||||
|
||||
return $assocName;
|
||||
}
|
||||
}
|
||||
@@ -1844,34 +1844,34 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
{
|
||||
$this->isReadOnly = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A numerically indexed list of field names of this persistent class.
|
||||
*
|
||||
*
|
||||
* This array includes identifier fields if present on this class.
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFieldNames()
|
||||
{
|
||||
return array_keys($this->fieldMappings);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A numerically indexed list of association names of this persistent class.
|
||||
*
|
||||
*
|
||||
* This array includes identifier associations if present on this class.
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAssociationNames()
|
||||
{
|
||||
return array_keys($this->associationMappings);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the target class name of the given association.
|
||||
*
|
||||
*
|
||||
* @param string $assocName
|
||||
* @return string
|
||||
*/
|
||||
@@ -1882,10 +1882,10 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
}
|
||||
return $this->associationMappings[$assocName]['targetEntity'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get fully-qualified class name of this persistent class.
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
@@ -1893,10 +1893,46 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) identifier column names for safe use in an SQL statement.
|
||||
*
|
||||
* @param AbstractPlatform $platform
|
||||
* @return array
|
||||
*/
|
||||
public function getQuotedIdentifierColumnNames($platform)
|
||||
{
|
||||
$quotedColumnNames = array();
|
||||
|
||||
foreach ($this->identifier as $idProperty) {
|
||||
if (isset($this->fieldMappings[$idProperty])) {
|
||||
$quotedColumnNames[] = isset($this->fieldMappings[$idProperty]['quoted'])
|
||||
? $platform->quoteIdentifier($this->fieldMappings[$idProperty]['columnName'])
|
||||
: $this->fieldMappings[$idProperty]['columnName'];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Association defined as Id field
|
||||
$joinColumns = $this->associationMappings[$idProperty]['joinColumns'];
|
||||
$assocQuotedColumnNames = array_map(
|
||||
function ($joinColumn) {
|
||||
return isset($joinColumn['quoted'])
|
||||
? $platform->quoteIdentifier($joinColumn['name'])
|
||||
: $joinColumn['name'];
|
||||
},
|
||||
$joinColumns
|
||||
);
|
||||
|
||||
$quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames);
|
||||
}
|
||||
|
||||
return $quotedColumnNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) column name of a mapped field for safe use
|
||||
* in an SQL statement.
|
||||
*
|
||||
*
|
||||
* @param string $field
|
||||
* @param AbstractPlatform $platform
|
||||
* @return string
|
||||
@@ -1907,11 +1943,11 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
$platform->quoteIdentifier($this->fieldMappings[$field]['columnName']) :
|
||||
$this->fieldMappings[$field]['columnName'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) primary table name of this class for safe use
|
||||
* in an SQL statement.
|
||||
*
|
||||
*
|
||||
* @param AbstractPlatform $platform
|
||||
* @return string
|
||||
*/
|
||||
@@ -1934,4 +1970,14 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
? $platform->quoteIdentifier($assoc['joinTable']['name'])
|
||||
: $assoc['joinTable']['name'];
|
||||
}
|
||||
|
||||
public function isAssociationInverseSide($fieldName)
|
||||
{
|
||||
return isset($this->associationMappings[$fieldName]) && !$this->associationMappings[$fieldName]['isOwningSide'];
|
||||
}
|
||||
|
||||
public function getAssociationMappedByTargetField($fieldName)
|
||||
{
|
||||
return $this->associationMappings[$fieldName]['mappedBy'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class XmlDriver extends AbstractFileDriver
|
||||
if (isset($xmlRoot['schema'])) {
|
||||
$metadata->table['schema'] = (string)$xmlRoot['schema'];
|
||||
}*/
|
||||
|
||||
|
||||
if (isset($xmlRoot['inheritance-type'])) {
|
||||
$inheritanceType = (string)$xmlRoot['inheritance-type'];
|
||||
$metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceType));
|
||||
@@ -210,7 +210,7 @@ class XmlDriver extends AbstractFileDriver
|
||||
$associationIds = array();
|
||||
foreach ($xmlRoot->id as $idElement) {
|
||||
if ((bool)$idElement['association-key'] == true) {
|
||||
$associationIds[(string)$idElement['fieldName']] = true;
|
||||
$associationIds[(string)$idElement['name']] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -322,8 +322,10 @@ class XmlDriver extends AbstractFileDriver
|
||||
$mapping['orderBy'] = $orderBy;
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement->{'index-by'})) {
|
||||
$mapping['indexBy'] = (string)$oneToManyElement->{'index-by'};
|
||||
if (isset($oneToManyElement['index-by'])) {
|
||||
$mapping['indexBy'] = (string)$oneToManyElement['index-by'];
|
||||
} else if (isset($oneToManyElement->{'index-by'})) {
|
||||
throw new \InvalidArgumentException("<index-by /> is not a valid tag");
|
||||
}
|
||||
|
||||
$metadata->mapOneToMany($mapping);
|
||||
@@ -429,8 +431,10 @@ class XmlDriver extends AbstractFileDriver
|
||||
$mapping['orderBy'] = $orderBy;
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement->{'index-by'})) {
|
||||
$mapping['indexBy'] = (string)$manyToManyElement->{'index-by'};
|
||||
if (isset($manyToManyElement['index-by'])) {
|
||||
$mapping['indexBy'] = (string)$manyToManyElement['index-by'];
|
||||
} else if (isset($manyToManyElement->{'index-by'})) {
|
||||
throw new \InvalidArgumentException("<index-by /> is not a valid tag");
|
||||
}
|
||||
|
||||
$metadata->mapManyToMany($mapping);
|
||||
|
||||
@@ -60,6 +60,15 @@ class ORMException extends Exception
|
||||
return new self("Unrecognized field: $field");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $field
|
||||
*/
|
||||
public static function invalidOrientation($className, $field)
|
||||
{
|
||||
return new self("Invalid order by orientation specified for " . $className . "#" . $field);
|
||||
}
|
||||
|
||||
public static function invalidFlushMode($mode)
|
||||
{
|
||||
return new self("'$mode' is an invalid flush mode.");
|
||||
|
||||
@@ -66,7 +66,7 @@ final class PersistentCollection implements Collection
|
||||
/**
|
||||
* The EntityManager that manages the persistence of the collection.
|
||||
*
|
||||
* @var Doctrine\ORM\EntityManager
|
||||
* @var \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
private $em;
|
||||
|
||||
@@ -93,21 +93,21 @@ final class PersistentCollection implements Collection
|
||||
|
||||
/**
|
||||
* Whether the collection has already been initialized.
|
||||
*
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $initialized = true;
|
||||
|
||||
|
||||
/**
|
||||
* The wrapped Collection instance.
|
||||
*
|
||||
*
|
||||
* @var Collection
|
||||
*/
|
||||
private $coll;
|
||||
|
||||
/**
|
||||
* Creates a new persistent collection.
|
||||
*
|
||||
*
|
||||
* @param EntityManager $em The EntityManager the collection will be associated with.
|
||||
* @param ClassMetadata $class The class descriptor of the entity type of this collection.
|
||||
* @param array The collection elements.
|
||||
@@ -144,7 +144,7 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
|
||||
public function getTypeClass()
|
||||
{
|
||||
return $this->typeClass;
|
||||
@@ -154,7 +154,7 @@ final class PersistentCollection implements Collection
|
||||
* INTERNAL:
|
||||
* Adds an element to a collection during hydration. This will automatically
|
||||
* complete bidirectional associations in the case of a one-to-many association.
|
||||
*
|
||||
*
|
||||
* @param mixed $element The element to add.
|
||||
*/
|
||||
public function hydrateAdd($element)
|
||||
@@ -172,7 +172,7 @@ final class PersistentCollection implements Collection
|
||||
$this->owner);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Sets a keyed element in the collection during hydration.
|
||||
@@ -265,13 +265,13 @@ final class PersistentCollection implements Collection
|
||||
/**
|
||||
* INTERNAL: Gets the association mapping of the collection.
|
||||
*
|
||||
* @return Doctrine\ORM\Mapping\AssociationMapping
|
||||
* @return \Doctrine\ORM\Mapping\AssociationMapping
|
||||
*/
|
||||
public function getMapping()
|
||||
{
|
||||
return $this->association;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Marks this collection as changed/dirty.
|
||||
*/
|
||||
@@ -306,17 +306,17 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
$this->isDirty = $dirty;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the initialized flag of the collection, forcing it into that state.
|
||||
*
|
||||
*
|
||||
* @param boolean $bool
|
||||
*/
|
||||
public function setInitialized($bool)
|
||||
{
|
||||
$this->initialized = $bool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether this collection has been initialized.
|
||||
*
|
||||
@@ -377,7 +377,7 @@ final class PersistentCollection implements Collection
|
||||
$this->em->getUnitOfWork()->getCollectionPersister($this->association)
|
||||
->deleteRows($this, $element);
|
||||
}*/
|
||||
|
||||
|
||||
$this->initialize();
|
||||
$removed = $this->coll->removeElement($element);
|
||||
if ($removed) {
|
||||
@@ -410,7 +410,7 @@ final class PersistentCollection implements Collection
|
||||
->getCollectionPersister($this->association)
|
||||
->contains($this, $element);
|
||||
}
|
||||
|
||||
|
||||
$this->initialize();
|
||||
return $this->coll->contains($element);
|
||||
}
|
||||
@@ -468,7 +468,7 @@ final class PersistentCollection implements Collection
|
||||
if (!$this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
|
||||
return $this->em->getUnitOfWork()
|
||||
->getCollectionPersister($this->association)
|
||||
->count($this) + $this->coll->count();
|
||||
->count($this) + ($this->isDirty ? $this->coll->count() : 0);
|
||||
}
|
||||
|
||||
$this->initialize();
|
||||
@@ -503,7 +503,7 @@ final class PersistentCollection implements Collection
|
||||
$this->initialize();
|
||||
return $this->coll->isEmpty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -530,7 +530,7 @@ final class PersistentCollection implements Collection
|
||||
$this->initialize();
|
||||
return $this->coll->filter($p);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -548,7 +548,7 @@ final class PersistentCollection implements Collection
|
||||
$this->initialize();
|
||||
return $this->coll->partition($p);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -567,6 +567,9 @@ final class PersistentCollection implements Collection
|
||||
return;
|
||||
}
|
||||
if ($this->association['type'] == ClassMetadata::ONE_TO_MANY && $this->association['orphanRemoval']) {
|
||||
// we need to initialize here, as orphan removal acts like implicit cascadeRemove,
|
||||
// hence for event listeners we need the objects in memory.
|
||||
$this->initialize();
|
||||
foreach ($this->coll as $element) {
|
||||
$this->em->getUnitOfWork()->scheduleOrphanRemoval($element);
|
||||
}
|
||||
@@ -579,7 +582,7 @@ final class PersistentCollection implements Collection
|
||||
$this->takeSnapshot();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by PHP when this collection is serialized. Ensures that only the
|
||||
* elements are properly serialized.
|
||||
@@ -591,7 +594,7 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return array('coll', 'initialized');
|
||||
}
|
||||
|
||||
|
||||
/* ArrayAccess implementation */
|
||||
|
||||
/**
|
||||
@@ -629,12 +632,12 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return $this->remove($offset);
|
||||
}
|
||||
|
||||
|
||||
public function key()
|
||||
{
|
||||
return $this->coll->key();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the element of the collection at the current iterator position.
|
||||
*/
|
||||
@@ -642,7 +645,7 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return $this->coll->current();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the internal iterator position to the next element.
|
||||
*/
|
||||
@@ -650,7 +653,7 @@ final class PersistentCollection implements Collection
|
||||
{
|
||||
return $this->coll->next();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the wrapped Collection instance.
|
||||
*/
|
||||
@@ -672,7 +675,10 @@ final class PersistentCollection implements Collection
|
||||
*/
|
||||
public function slice($offset, $length = null)
|
||||
{
|
||||
if (!$this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
|
||||
if ( ! $this->initialized &&
|
||||
! $this->isDirty &&
|
||||
$this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
|
||||
|
||||
return $this->em->getUnitOfWork()
|
||||
->getCollectionPersister($this->association)
|
||||
->slice($this, $offset, $length);
|
||||
|
||||
@@ -36,19 +36,19 @@ abstract class AbstractCollectionPersister
|
||||
protected $_em;
|
||||
|
||||
/**
|
||||
* @var Doctrine\DBAL\Connection
|
||||
* @var \Doctrine\DBAL\Connection
|
||||
*/
|
||||
protected $_conn;
|
||||
|
||||
/**
|
||||
* @var Doctrine\ORM\UnitOfWork
|
||||
* @var \Doctrine\ORM\UnitOfWork
|
||||
*/
|
||||
protected $_uow;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of a class derived from AbstractCollectionPersister.
|
||||
*
|
||||
* @param Doctrine\ORM\EntityManager $em
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
@@ -65,9 +65,11 @@ abstract class AbstractCollectionPersister
|
||||
public function delete(PersistentCollection $coll)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
|
||||
if ( ! $mapping['isOwningSide']) {
|
||||
return; // ignore inverse side
|
||||
}
|
||||
|
||||
$sql = $this->_getDeleteSQL($coll);
|
||||
$this->_conn->executeUpdate($sql, $this->_getDeleteSQLParameters($coll));
|
||||
}
|
||||
@@ -96,9 +98,11 @@ abstract class AbstractCollectionPersister
|
||||
public function update(PersistentCollection $coll)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
|
||||
if ( ! $mapping['isOwningSide']) {
|
||||
return; // ignore inverse side
|
||||
}
|
||||
|
||||
$this->deleteRows($coll);
|
||||
//$this->updateRows($coll);
|
||||
$this->insertRows($coll);
|
||||
@@ -108,6 +112,7 @@ abstract class AbstractCollectionPersister
|
||||
{
|
||||
$deleteDiff = $coll->getDeleteDiff();
|
||||
$sql = $this->_getDeleteRowSQL($coll);
|
||||
|
||||
foreach ($deleteDiff as $element) {
|
||||
$this->_conn->executeUpdate($sql, $this->_getDeleteRowSQLParameters($coll, $element));
|
||||
}
|
||||
@@ -120,6 +125,7 @@ abstract class AbstractCollectionPersister
|
||||
{
|
||||
$insertDiff = $coll->getInsertDiff();
|
||||
$sql = $this->_getInsertRowSQL($coll);
|
||||
|
||||
foreach ($insertDiff as $element) {
|
||||
$this->_conn->executeUpdate($sql, $this->_getInsertRowSQLParameters($coll, $element));
|
||||
}
|
||||
|
||||
@@ -39,10 +39,12 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
|
||||
protected function _prepareInsertData($entity)
|
||||
{
|
||||
$data = parent::_prepareInsertData($entity);
|
||||
|
||||
// Populate the discriminator column
|
||||
$discColumn = $this->_class->discriminatorColumn;
|
||||
$this->_columnTypes[$discColumn['name']] = $discColumn['type'];
|
||||
$data[$this->_getDiscriminatorColumnTableName()][$discColumn['name']] = $this->_class->discriminatorValue;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -63,7 +65,7 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
|
||||
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
||||
$this->_rsm->addFieldResult($alias, $columnAlias, $field, $class->name);
|
||||
|
||||
return "$sql AS $columnAlias";
|
||||
return $sql . ' AS ' . $columnAlias;
|
||||
}
|
||||
|
||||
protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $className)
|
||||
@@ -72,6 +74,6 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
|
||||
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
||||
$this->_rsm->addMetaResult('r', $resultColumnName, $joinColumnName);
|
||||
|
||||
return $tableAlias . ".$joinColumnName AS $columnAlias";
|
||||
return $tableAlias . '.' . $joinColumnName . ' AS ' . $columnAlias;
|
||||
}
|
||||
}
|
||||
@@ -78,28 +78,28 @@ class BasicEntityPersister
|
||||
/**
|
||||
* Metadata object that describes the mapping of the mapped entity class.
|
||||
*
|
||||
* @var Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @var \Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
protected $_class;
|
||||
|
||||
/**
|
||||
* The underlying DBAL Connection of the used EntityManager.
|
||||
*
|
||||
* @var Doctrine\DBAL\Connection $conn
|
||||
* @var \Doctrine\DBAL\Connection $conn
|
||||
*/
|
||||
protected $_conn;
|
||||
|
||||
/**
|
||||
* The database platform.
|
||||
*
|
||||
* @var Doctrine\DBAL\Platforms\AbstractPlatform
|
||||
*
|
||||
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
|
||||
*/
|
||||
protected $_platform;
|
||||
|
||||
/**
|
||||
* The EntityManager instance.
|
||||
*
|
||||
* @var Doctrine\ORM\EntityManager
|
||||
* @var \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
@@ -109,12 +109,12 @@ class BasicEntityPersister
|
||||
* @var array
|
||||
*/
|
||||
protected $_queuedInserts = array();
|
||||
|
||||
|
||||
/**
|
||||
* ResultSetMapping that is used for all queries. Is generated lazily once per request.
|
||||
*
|
||||
*
|
||||
* TODO: Evaluate Caching in combination with the other cached SQL snippets.
|
||||
*
|
||||
*
|
||||
* @var Query\ResultSetMapping
|
||||
*/
|
||||
protected $_rsm;
|
||||
@@ -122,7 +122,7 @@ class BasicEntityPersister
|
||||
/**
|
||||
* The map of column names to DBAL mapping types of all prepared columns used
|
||||
* when INSERTing or UPDATEing an entity.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
* @see _prepareInsertData($entity)
|
||||
* @see _prepareUpdateData($entity)
|
||||
@@ -132,7 +132,7 @@ class BasicEntityPersister
|
||||
/**
|
||||
* The INSERT SQL statement used for entities handled by this persister.
|
||||
* This SQL is only generated once per request, if at all.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_insertSql;
|
||||
@@ -140,29 +140,29 @@ class BasicEntityPersister
|
||||
/**
|
||||
* The SELECT column list SQL fragment used for querying entities by this persister.
|
||||
* This SQL fragment is only generated once per request, if at all.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_selectColumnListSql;
|
||||
|
||||
|
||||
/**
|
||||
* The JOIN SQL fragement used to eagerly load all many-to-one and one-to-one
|
||||
* associations configured as FETCH_EAGER, aswell as all inverse one-to-one associations.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_selectJoinSql;
|
||||
|
||||
/**
|
||||
* Counter for creating unique SQL table and column aliases.
|
||||
*
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_sqlAliasCounter = 0;
|
||||
|
||||
/**
|
||||
* Map from class names (FQCN) to the corresponding generated SQL table aliases.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_sqlTableAliases = array();
|
||||
@@ -170,9 +170,9 @@ class BasicEntityPersister
|
||||
/**
|
||||
* Initializes a new <tt>BasicEntityPersister</tt> that uses the given EntityManager
|
||||
* and persists instances of the class described by the given ClassMetadata descriptor.
|
||||
*
|
||||
* @param Doctrine\ORM\EntityManager $em
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
*
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
*/
|
||||
public function __construct(EntityManager $em, ClassMetadata $class)
|
||||
{
|
||||
@@ -183,7 +183,7 @@ class BasicEntityPersister
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @return \Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
public function getClassMetadata()
|
||||
{
|
||||
@@ -204,7 +204,7 @@ class BasicEntityPersister
|
||||
/**
|
||||
* Executes all queued entity insertions and returns any generated post-insert
|
||||
* identifiers that were created as a result of the insertions.
|
||||
*
|
||||
*
|
||||
* If no inserts are queued, invoking this method is a NOOP.
|
||||
*
|
||||
* @return array An array of any generated post-insert IDs. This will be an empty array
|
||||
@@ -228,6 +228,7 @@ class BasicEntityPersister
|
||||
|
||||
if (isset($insertData[$tableName])) {
|
||||
$paramIndex = 1;
|
||||
|
||||
foreach ($insertData[$tableName] as $column => $value) {
|
||||
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$column]);
|
||||
}
|
||||
@@ -255,7 +256,7 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Retrieves the default version value which was created
|
||||
* by the preceding INSERT statement and assigns it back in to the
|
||||
* by the preceding INSERT statement and assigns it back in to the
|
||||
* entities version field.
|
||||
*
|
||||
* @param object $entity
|
||||
@@ -269,8 +270,8 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Fetch the current version value of a versioned entity.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $versionedClass
|
||||
*
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $versionedClass
|
||||
* @param mixed $id
|
||||
* @return mixed
|
||||
*/
|
||||
@@ -294,7 +295,7 @@ class BasicEntityPersister
|
||||
* The data to update is retrieved through {@link _prepareUpdateData}.
|
||||
* Subclasses that override this method are supposed to obtain the update data
|
||||
* in the same way, through {@link _prepareUpdateData}.
|
||||
*
|
||||
*
|
||||
* Subclasses are also supposed to take care of versioning when overriding this method,
|
||||
* if necessary. The {@link _updateTable} method can be used to apply the data retrieved
|
||||
* from {@_prepareUpdateData} on the target tables, thereby optionally applying versioning.
|
||||
@@ -392,7 +393,7 @@ class BasicEntityPersister
|
||||
// @Todo this only covers scenarios with no inheritance or of the same level. Is there something
|
||||
// like self-referential relationship between different levels of an inheritance hierachy? I hope not!
|
||||
$selfReferential = ($mapping['targetEntity'] == $mapping['sourceEntity']);
|
||||
|
||||
|
||||
if ( ! $mapping['isOwningSide']) {
|
||||
$relatedClass = $this->_em->getClassMetadata($mapping['targetEntity']);
|
||||
$mapping = $relatedClass->associationMappings[$mapping['mappedBy']];
|
||||
@@ -441,7 +442,7 @@ class BasicEntityPersister
|
||||
* Prepares the changeset of an entity for database insertion (UPDATE).
|
||||
*
|
||||
* The changeset is obtained from the currently running UnitOfWork.
|
||||
*
|
||||
*
|
||||
* During this preparation the array that is passed as the second parameter is filled with
|
||||
* <columnName> => <value> pairs, grouped by table name.
|
||||
*
|
||||
@@ -567,7 +568,7 @@ class BasicEntityPersister
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, $lockMode);
|
||||
list($params, $types) = $this->expandParameters($criteria);
|
||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||
|
||||
|
||||
if ($entity !== null) {
|
||||
$hints[Query::HINT_REFRESH] = true;
|
||||
$hints[Query::HINT_REFRESH_ENTITY] = $entity;
|
||||
@@ -657,7 +658,7 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Refreshes a managed entity.
|
||||
*
|
||||
*
|
||||
* @param array $id The identifier of the entity as an associative array from
|
||||
* column or field names to values.
|
||||
* @param object $entity The entity to refresh.
|
||||
@@ -667,7 +668,7 @@ class BasicEntityPersister
|
||||
$sql = $this->_getSelectEntitiesSQL($id);
|
||||
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));
|
||||
|
||||
@@ -682,7 +683,7 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Loads a list of entities by a list of field criteria.
|
||||
*
|
||||
*
|
||||
* @param array $criteria
|
||||
* @param array $orderBy
|
||||
* @param int $limit
|
||||
@@ -706,7 +707,7 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Get (sliced or full) elements of the given collection.
|
||||
*
|
||||
*
|
||||
* @param array $assoc
|
||||
* @param object $sourceEntity
|
||||
* @param int|null $offset
|
||||
@@ -721,9 +722,9 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Load an array of entities from a given dbal statement.
|
||||
*
|
||||
*
|
||||
* @param array $assoc
|
||||
* @param Doctrine\DBAL\Statement $stmt
|
||||
* @param \Doctrine\DBAL\Statement $stmt
|
||||
* @return array
|
||||
*/
|
||||
private function loadArrayFromStatement($assoc, $stmt)
|
||||
@@ -743,13 +744,13 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Hydrate a collection from a given dbal statement.
|
||||
*
|
||||
*
|
||||
* @param array $assoc
|
||||
* @param Doctrine\DBAL\Statement $stmt
|
||||
* @param \Doctrine\DBAL\Statement $stmt
|
||||
* @param PersistentCollection $coll
|
||||
*/
|
||||
private function loadCollectionFromStatement($assoc, $stmt, $coll)
|
||||
{
|
||||
{
|
||||
$hints = array('deferEagerLoads' => true, 'collection' => $coll);
|
||||
|
||||
if (isset($assoc['indexBy'])) {
|
||||
@@ -791,7 +792,7 @@ class BasicEntityPersister
|
||||
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
||||
if (isset($sourceClass->associationMappings[$field])) {
|
||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
||||
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
|
||||
}
|
||||
|
||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
|
||||
@@ -813,7 +814,7 @@ class BasicEntityPersister
|
||||
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
||||
if (isset($sourceClass->associationMappings[$field])) {
|
||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
||||
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
|
||||
}
|
||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
|
||||
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
@@ -872,11 +873,10 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Gets the ORDER BY SQL snippet for ordered collections.
|
||||
*
|
||||
*
|
||||
* @param array $orderBy
|
||||
* @param string $baseTableAlias
|
||||
* @return string
|
||||
* @todo Rename: _getOrderBySQL
|
||||
*/
|
||||
protected final function _getOrderBySQL(array $orderBy, $baseTableAlias)
|
||||
{
|
||||
@@ -886,6 +886,11 @@ class BasicEntityPersister
|
||||
throw ORMException::unrecognizedField($fieldName);
|
||||
}
|
||||
|
||||
$orientation = strtoupper(trim($orientation));
|
||||
if ($orientation != 'ASC' && $orientation != 'DESC') {
|
||||
throw ORMException::invalidOrientation($this->_class->name, $fieldName);
|
||||
}
|
||||
|
||||
$tableAlias = isset($this->_class->fieldMappings[$fieldName]['inherited']) ?
|
||||
$this->_getSQLTableAlias($this->_class->fieldMappings[$fieldName]['inherited'])
|
||||
: $baseTableAlias;
|
||||
@@ -906,7 +911,7 @@ class BasicEntityPersister
|
||||
* list SQL fragment. Note that in the implementation of BasicEntityPersister
|
||||
* the resulting SQL fragment is generated only once and cached in {@link _selectColumnListSql}.
|
||||
* Subclasses may or may not do the same.
|
||||
*
|
||||
*
|
||||
* @return string The SQL fragment.
|
||||
* @todo Rename: _getSelectColumnsSQL()
|
||||
*/
|
||||
@@ -934,21 +939,21 @@ class BasicEntityPersister
|
||||
if ($columnList) $columnList .= ', ';
|
||||
$columnList .= $assocColumnSQL;
|
||||
}
|
||||
|
||||
|
||||
if ($assoc['type'] & ClassMetadata::TO_ONE && ($assoc['fetch'] == ClassMetadata::FETCH_EAGER || !$assoc['isOwningSide'])) {
|
||||
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||
if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||
continue; // now this is why you shouldn't use inheritance
|
||||
}
|
||||
|
||||
|
||||
$assocAlias = 'e' . ($eagerAliasCounter++);
|
||||
$this->_rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField);
|
||||
|
||||
|
||||
foreach ($eagerEntity->fieldNames AS $field) {
|
||||
if ($columnList) $columnList .= ', ';
|
||||
$columnList .= $this->_getSelectColumnSQL($field, $eagerEntity, $assocAlias);
|
||||
}
|
||||
|
||||
|
||||
foreach ($eagerEntity->associationMappings as $assoc2Field => $assoc2) {
|
||||
$assoc2ColumnSQL = $this->_getSelectColumnAssociationSQL($assoc2Field, $assoc2, $eagerEntity, $assocAlias);
|
||||
if ($assoc2ColumnSQL) {
|
||||
@@ -960,7 +965,7 @@ class BasicEntityPersister
|
||||
$first = true;
|
||||
if ($assoc['isOwningSide']) {
|
||||
$this->_selectJoinSql .= ' ' . $eagerEntity->table['name'] . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON ';
|
||||
|
||||
|
||||
foreach ($assoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
||||
if (!$first) {
|
||||
$this->_selectJoinSql .= ' AND ';
|
||||
@@ -972,7 +977,7 @@ class BasicEntityPersister
|
||||
} else {
|
||||
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||
$owningAssoc = $eagerEntity->getAssociationMapping($assoc['mappedBy']);
|
||||
|
||||
|
||||
$this->_selectJoinSql .= ' ' . $eagerEntity->table['name'] . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON ';
|
||||
|
||||
foreach ($owningAssoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
||||
@@ -991,7 +996,7 @@ class BasicEntityPersister
|
||||
|
||||
return $this->_selectColumnListSql;
|
||||
}
|
||||
|
||||
|
||||
protected function _getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class, $alias = 'r')
|
||||
{
|
||||
$columnList = '';
|
||||
@@ -1000,9 +1005,10 @@ class BasicEntityPersister
|
||||
if ($columnList) $columnList .= ', ';
|
||||
|
||||
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
|
||||
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) ) . ".$srcColumn AS $columnAlias";
|
||||
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
||||
$this->_rsm->addMetaResult($alias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
|
||||
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
|
||||
. '.' . $srcColumn . ' AS ' . $resultColumnName;
|
||||
$this->_rsm->addMetaResult($alias, $resultColumnName, $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
|
||||
}
|
||||
}
|
||||
return $columnList;
|
||||
@@ -1024,9 +1030,9 @@ class BasicEntityPersister
|
||||
$owningAssoc = $this->_em->getClassMetadata($manyToMany['targetEntity'])->associationMappings[$manyToMany['mappedBy']];
|
||||
$joinClauses = $owningAssoc['relationToSourceKeyColumns'];
|
||||
}
|
||||
|
||||
|
||||
$joinTableName = $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
||||
|
||||
|
||||
$joinSql = '';
|
||||
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
|
||||
if ($joinSql != '') $joinSql .= ' AND ';
|
||||
@@ -1047,7 +1053,7 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Gets the INSERT SQL used by the persister to persist a new entity.
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _getInsertSQL()
|
||||
@@ -1124,7 +1130,7 @@ class BasicEntityPersister
|
||||
|
||||
/**
|
||||
* Gets the SQL table alias for the given class name.
|
||||
*
|
||||
*
|
||||
* @param string $className
|
||||
* @return string The SQL table alias.
|
||||
* @todo Reconsider. Binding table aliases to class names is not such a good idea.
|
||||
@@ -1134,7 +1140,7 @@ class BasicEntityPersister
|
||||
if ($assocName) {
|
||||
$className .= '#'.$assocName;
|
||||
}
|
||||
|
||||
|
||||
if (isset($this->_sqlTableAliases[$className])) {
|
||||
return $this->_sqlTableAliases[$className];
|
||||
}
|
||||
@@ -1266,7 +1272,7 @@ class BasicEntityPersister
|
||||
* @param object $sourceEntity
|
||||
* @param int|null $offset
|
||||
* @param int|null $limit
|
||||
* @return Doctrine\DBAL\Statement
|
||||
* @return \Doctrine\DBAL\Statement
|
||||
*/
|
||||
private function getOneToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null)
|
||||
{
|
||||
@@ -1284,7 +1290,7 @@ class BasicEntityPersister
|
||||
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
||||
if (isset($sourceClass->associationMappings[$field])) {
|
||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
||||
$value = $value[$this->_em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
|
||||
}
|
||||
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
|
||||
} else {
|
||||
@@ -1314,13 +1320,12 @@ class BasicEntityPersister
|
||||
}
|
||||
|
||||
$type = null;
|
||||
if (isset($this->_class->fieldMappings[$field])) {
|
||||
$type = Type::getType($this->_class->fieldMappings[$field]['type'])->getBindingType();
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$type = Type::getType( $this->_class->fieldMappings[$field]['type'] )->getBindingType();
|
||||
$type += Connection::ARRAY_PARAM_OFFSET;
|
||||
} else if (isset($this->_class->fieldMappings[$field])) {
|
||||
$type = $this->_class->fieldMappings[$field]['type'];
|
||||
}
|
||||
|
||||
$params[] = $value;
|
||||
$types[] = $type;
|
||||
}
|
||||
@@ -1340,8 +1345,7 @@ class BasicEntityPersister
|
||||
$criteria = array_merge($criteria, $extraConditions);
|
||||
}
|
||||
|
||||
$sql = 'SELECT 1 FROM ' . $this->_class->getQuotedTableName($this->_platform)
|
||||
. ' ' . $this->_getSQLTableAlias($this->_class->name)
|
||||
$sql = 'SELECT 1 ' . $this->getLockTablesSql()
|
||||
. ' WHERE ' . $this->_getSelectConditionSQL($criteria);
|
||||
|
||||
return (bool) $this->_conn->fetchColumn($sql, array_values($criteria));
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Doctrine\ORM\Persisters;
|
||||
use Doctrine\ORM\ORMException,
|
||||
Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\DBAL\LockMode,
|
||||
Doctrine\DBAL\Types\Type,
|
||||
Doctrine\ORM\Query\ResultSetMapping;
|
||||
|
||||
/**
|
||||
@@ -66,7 +67,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
* This function finds the ClassMetadata instance in an inheritance hierarchy
|
||||
* that is responsible for enabling versioning.
|
||||
*
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @return \Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
private function _getVersionedClassMetadata()
|
||||
{
|
||||
@@ -143,9 +144,11 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
|
||||
// Execute insert on root table
|
||||
$paramIndex = 1;
|
||||
|
||||
foreach ($insertData[$rootTableName] as $columnName => $value) {
|
||||
$rootTableStmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
||||
}
|
||||
|
||||
$rootTableStmt->execute();
|
||||
|
||||
if ($isPostInsertId) {
|
||||
@@ -160,12 +163,17 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
foreach ($subTableStmts as $tableName => $stmt) {
|
||||
$data = isset($insertData[$tableName]) ? $insertData[$tableName] : array();
|
||||
$paramIndex = 1;
|
||||
foreach ((array) $id as $idVal) {
|
||||
$stmt->bindValue($paramIndex++, $idVal);
|
||||
|
||||
foreach ((array) $id as $idName => $idVal) {
|
||||
$type = isset($this->_columnTypes[$idName]) ? $this->_columnTypes[$idName] : Type::STRING;
|
||||
|
||||
$stmt->bindValue($paramIndex++, $idVal, $type);
|
||||
}
|
||||
|
||||
foreach ($data as $columnName => $value) {
|
||||
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
@@ -191,7 +199,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
{
|
||||
$updateData = $this->_prepareUpdateData($entity);
|
||||
|
||||
if ($isVersioned = $this->_class->isVersioned) {
|
||||
if (($isVersioned = $this->_class->isVersioned) != false) {
|
||||
$versionedClass = $this->_getVersionedClassMetadata();
|
||||
$versionedTable = $versionedClass->table['name'];
|
||||
}
|
||||
@@ -200,6 +208,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
foreach ($updateData as $tableName => $data) {
|
||||
$this->_updateTable($entity, $this->_quotedTableMap[$tableName], $data, $isVersioned && $versionedTable == $tableName);
|
||||
}
|
||||
|
||||
// Make sure the table with the version column is updated even if no columns on that
|
||||
// table were affected.
|
||||
if ($isVersioned && ! isset($updateData[$versionedTable])) {
|
||||
@@ -229,6 +238,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
} else {
|
||||
// Delete from all tables individually, starting from this class' table up to the root table.
|
||||
$this->_conn->delete($this->_class->getQuotedTableName($this->_platform), $id);
|
||||
|
||||
foreach ($this->_class->parentClasses as $parentClass) {
|
||||
$this->_conn->delete($this->_em->getClassMetadata($parentClass)->getQuotedTableName($this->_platform), $id);
|
||||
}
|
||||
|
||||
@@ -39,9 +39,10 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
*/
|
||||
protected function _getDeleteRowSQL(PersistentCollection $coll)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
$mapping = $coll->getMapping();
|
||||
$joinTable = $mapping['joinTable'];
|
||||
$columns = $mapping['joinTableColumns'];
|
||||
$columns = $mapping['joinTableColumns'];
|
||||
|
||||
return 'DELETE FROM ' . $joinTable['name'] . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?';
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,10 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
|
||||
/** {@inheritdoc} */
|
||||
protected function _getSelectColumnListSQL()
|
||||
{
|
||||
if ($this->_selectColumnListSql !== null) {
|
||||
return $this->_selectColumnListSql;
|
||||
}
|
||||
|
||||
$columnList = parent::_getSelectColumnListSQL();
|
||||
|
||||
// Append discriminator column
|
||||
@@ -74,7 +78,8 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
|
||||
}
|
||||
}
|
||||
|
||||
return $columnList;
|
||||
$this->_selectColumnListSql = $columnList;
|
||||
return $this->_selectColumnListSql;
|
||||
}
|
||||
|
||||
/** {@inheritdoc} */
|
||||
|
||||
@@ -165,11 +165,13 @@ class ProxyFactory
|
||||
{
|
||||
$methods = '';
|
||||
|
||||
$methodNames = array();
|
||||
foreach ($class->reflClass->getMethods() as $method) {
|
||||
/* @var $method ReflectionMethod */
|
||||
if ($method->isConstructor() || in_array(strtolower($method->getName()), array("__sleep", "__clone"))) {
|
||||
if ($method->isConstructor() || in_array(strtolower($method->getName()), array("__sleep", "__clone")) || isset($methodNames[$method->getName()])) {
|
||||
continue;
|
||||
}
|
||||
$methodNames[$method->getName()] = true;
|
||||
|
||||
if ($method->isPublic() && ! $method->isFinal() && ! $method->isStatic()) {
|
||||
$methods .= "\n" . ' public function ';
|
||||
|
||||
@@ -44,28 +44,28 @@ final class Query extends AbstractQuery
|
||||
* is called.
|
||||
*/
|
||||
const STATE_DIRTY = 2;
|
||||
|
||||
|
||||
/* Query HINTS */
|
||||
/**
|
||||
* The refresh hint turns any query into a refresh query with the result that
|
||||
* any local changes in entities are overridden with the fetched values.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const HINT_REFRESH = 'doctrine.refresh';
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Internal hint: is set to the proxy entity that is currently triggered for loading
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const HINT_REFRESH_ENTITY = 'doctrine.refresh.entity';
|
||||
|
||||
|
||||
/**
|
||||
* The forcePartialLoad query hint forces a particular query to return
|
||||
* partial objects.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
* @todo Rename: HINT_OPTIMIZE
|
||||
*/
|
||||
@@ -73,15 +73,15 @@ final class Query extends AbstractQuery
|
||||
/**
|
||||
* The includeMetaColumns query hint causes meta columns like foreign keys and
|
||||
* discriminator columns to be selected and returned as part of the query result.
|
||||
*
|
||||
*
|
||||
* This hint does only apply to non-object queries.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const HINT_INCLUDE_META_COLUMNS = 'doctrine.includeMetaColumns';
|
||||
|
||||
/**
|
||||
* An array of class names that implement Doctrine\ORM\Query\TreeWalker and
|
||||
* An array of class names that implement \Doctrine\ORM\Query\TreeWalker and
|
||||
* are iterated and executed after the DQL has been parsed into an AST.
|
||||
*
|
||||
* @var string
|
||||
@@ -89,7 +89,7 @@ final class Query extends AbstractQuery
|
||||
const HINT_CUSTOM_TREE_WALKERS = 'doctrine.customTreeWalkers';
|
||||
|
||||
/**
|
||||
* A string with a class name that implements Doctrine\ORM\Query\TreeWalker
|
||||
* A string with a class name that implements \Doctrine\ORM\Query\TreeWalker
|
||||
* and is used for generating the target SQL from any DQL AST tree.
|
||||
*
|
||||
* @var string
|
||||
@@ -119,15 +119,15 @@ final class Query extends AbstractQuery
|
||||
private $_dql = null;
|
||||
|
||||
/**
|
||||
* @var Doctrine\ORM\Query\ParserResult The parser result that holds DQL => SQL information.
|
||||
* @var \Doctrine\ORM\Query\ParserResult The parser result that holds DQL => SQL information.
|
||||
*/
|
||||
private $_parserResult;
|
||||
|
||||
|
||||
/**
|
||||
* @var integer The first result to return (the "offset").
|
||||
*/
|
||||
private $_firstResult = null;
|
||||
|
||||
|
||||
/**
|
||||
* @var integer The maximum number of results to return (the "limit").
|
||||
*/
|
||||
@@ -147,7 +147,7 @@ final class Query extends AbstractQuery
|
||||
* @var int Query Cache lifetime.
|
||||
*/
|
||||
private $_queryCacheTTL;
|
||||
|
||||
|
||||
/**
|
||||
* @var boolean Whether to use a query cache, if available. Defaults to TRUE.
|
||||
*/
|
||||
@@ -158,7 +158,7 @@ final class Query extends AbstractQuery
|
||||
/**
|
||||
* Initializes a new Query instance.
|
||||
*
|
||||
* @param Doctrine\ORM\EntityManager $entityManager
|
||||
* @param \Doctrine\ORM\EntityManager $entityManager
|
||||
*/
|
||||
/*public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
@@ -179,9 +179,9 @@ final class Query extends AbstractQuery
|
||||
/**
|
||||
* Returns the corresponding AST for this DQL query.
|
||||
*
|
||||
* @return Doctrine\ORM\Query\AST\SelectStatement |
|
||||
* Doctrine\ORM\Query\AST\UpdateStatement |
|
||||
* Doctrine\ORM\Query\AST\DeleteStatement
|
||||
* @return \Doctrine\ORM\Query\AST\SelectStatement |
|
||||
* \Doctrine\ORM\Query\AST\UpdateStatement |
|
||||
* \Doctrine\ORM\Query\AST\DeleteStatement
|
||||
*/
|
||||
public function getAST()
|
||||
{
|
||||
@@ -191,21 +191,22 @@ final class Query extends AbstractQuery
|
||||
|
||||
/**
|
||||
* Parses the DQL query, if necessary, and stores the parser result.
|
||||
*
|
||||
*
|
||||
* Note: Populates $this->_parserResult as a side-effect.
|
||||
*
|
||||
* @return Doctrine\ORM\Query\ParserResult
|
||||
* @return \Doctrine\ORM\Query\ParserResult
|
||||
*/
|
||||
private function _parse()
|
||||
{
|
||||
if ($this->_state === self::STATE_CLEAN) {
|
||||
return $this->_parserResult;
|
||||
}
|
||||
|
||||
|
||||
// Check query cache.
|
||||
if ($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver())) {
|
||||
$hash = $this->_getQueryCacheId();
|
||||
$cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash);
|
||||
|
||||
if ($cached === false) {
|
||||
// Cache miss.
|
||||
$parser = new Parser($this);
|
||||
@@ -219,8 +220,9 @@ final class Query extends AbstractQuery
|
||||
$parser = new Parser($this);
|
||||
$this->_parserResult = $parser->parse();
|
||||
}
|
||||
|
||||
$this->_state = self::STATE_CLEAN;
|
||||
|
||||
|
||||
return $this->_parserResult;
|
||||
}
|
||||
|
||||
@@ -239,55 +241,62 @@ final class Query extends AbstractQuery
|
||||
}
|
||||
|
||||
list($sqlParams, $types) = $this->processParameterMappings($paramMappings);
|
||||
|
||||
|
||||
if ($this->_resultSetMapping === null) {
|
||||
$this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
|
||||
}
|
||||
|
||||
return $executor->execute($this->_em->getConnection(), $sqlParams, $types);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Processes query parameter mappings
|
||||
*
|
||||
*
|
||||
* @param array $paramMappings
|
||||
* @return array
|
||||
*/
|
||||
private function processParameterMappings($paramMappings)
|
||||
{
|
||||
$sqlParams = $types = array();
|
||||
|
||||
|
||||
foreach ($this->_params as $key => $value) {
|
||||
if ( ! isset($paramMappings[$key])) {
|
||||
throw QueryException::unknownParameter($key);
|
||||
}
|
||||
|
||||
|
||||
if (isset($this->_paramTypes[$key])) {
|
||||
foreach ($paramMappings[$key] as $position) {
|
||||
$types[$position] = $this->_paramTypes[$key];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$sqlPositions = $paramMappings[$key];
|
||||
$value = array_values($this->processParameterValue($value));
|
||||
$countValue = count($value);
|
||||
|
||||
|
||||
for ($i = 0, $l = count($sqlPositions); $i < $l; $i++) {
|
||||
$sqlParams[$sqlPositions[$i]] = $value[($i % $countValue)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (count($sqlParams) != count($types)) {
|
||||
throw QueryException::parameterTypeMissmatch();
|
||||
}
|
||||
|
||||
if ($sqlParams) {
|
||||
ksort($sqlParams);
|
||||
$sqlParams = array_values($sqlParams);
|
||||
|
||||
ksort($types);
|
||||
$types = array_values($types);
|
||||
}
|
||||
|
||||
return array($sqlParams, $types);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process an individual parameter value
|
||||
*
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
@@ -328,10 +337,10 @@ final class Query extends AbstractQuery
|
||||
$this->_queryCache = $queryCache;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines whether the query should make use of a query cache, if available.
|
||||
*
|
||||
*
|
||||
* @param boolean $bool
|
||||
* @return @return Query This query instance.
|
||||
*/
|
||||
@@ -419,7 +428,7 @@ final class Query extends AbstractQuery
|
||||
* Sets a DQL query string.
|
||||
*
|
||||
* @param string $dqlQuery DQL Query
|
||||
* @return Doctrine\ORM\AbstractQuery
|
||||
* @return \Doctrine\ORM\AbstractQuery
|
||||
*/
|
||||
public function setDQL($dqlQuery)
|
||||
{
|
||||
@@ -465,7 +474,7 @@ final class Query extends AbstractQuery
|
||||
{
|
||||
return stripos($this->getDQL(), $dql) === false ? false : true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the position of the first result to retrieve (the "offset").
|
||||
*
|
||||
@@ -478,21 +487,21 @@ final class Query extends AbstractQuery
|
||||
$this->_state = self::STATE_DIRTY;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the position of the first result the query object was set to retrieve (the "offset").
|
||||
* Returns NULL if {@link setFirstResult} was not applied to this query.
|
||||
*
|
||||
*
|
||||
* @return integer The position of the first result.
|
||||
*/
|
||||
public function getFirstResult()
|
||||
{
|
||||
return $this->_firstResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the maximum number of results to retrieve (the "limit").
|
||||
*
|
||||
*
|
||||
* @param integer $maxResults
|
||||
* @return Query This query object.
|
||||
*/
|
||||
@@ -502,11 +511,11 @@ final class Query extends AbstractQuery
|
||||
$this->_state = self::STATE_DIRTY;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the maximum number of results the query object was set to retrieve (the "limit").
|
||||
* Returns NULL if {@link setMaxResults} was not applied to this query.
|
||||
*
|
||||
*
|
||||
* @return integer Maximum number of results.
|
||||
*/
|
||||
public function getMaxResults()
|
||||
@@ -527,7 +536,7 @@ final class Query extends AbstractQuery
|
||||
$this->setHint(self::HINT_INTERNAL_ITERATION, true);
|
||||
return parent::iterate($params, $hydrationMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -536,7 +545,7 @@ final class Query extends AbstractQuery
|
||||
$this->_state = self::STATE_DIRTY;
|
||||
return parent::setHint($name, $value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -549,7 +558,7 @@ final class Query extends AbstractQuery
|
||||
/**
|
||||
* Set the lock mode for this Query.
|
||||
*
|
||||
* @see Doctrine\DBAL\LockMode
|
||||
* @see \Doctrine\DBAL\LockMode
|
||||
* @param int $lockMode
|
||||
* @return Query
|
||||
*/
|
||||
@@ -591,7 +600,7 @@ final class Query extends AbstractQuery
|
||||
ksort($this->_hints);
|
||||
|
||||
return md5(
|
||||
$this->getDql() . var_export($this->_hints, true) .
|
||||
$this->getDql() . var_export($this->_hints, true) .
|
||||
'&firstResult=' . $this->_firstResult . '&maxResult=' . $this->_maxResults .
|
||||
'&hydrationMode='.$this->_hydrationMode.'DOCTRINE_QUERY_CACHE_SALT'
|
||||
);
|
||||
@@ -607,4 +616,4 @@ final class Query extends AbstractQuery
|
||||
parent::__clone();
|
||||
$this->_state = self::STATE_DIRTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@ abstract class AbstractSqlExecutor
|
||||
/**
|
||||
* Executes all sql statements.
|
||||
*
|
||||
* @param Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
|
||||
* @param \Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
|
||||
* @param array $params The parameters.
|
||||
* @return Doctrine\DBAL\Driver\Statement
|
||||
* @return \Doctrine\DBAL\Driver\Statement
|
||||
*/
|
||||
abstract public function execute(Connection $conn, array $params, array $types);
|
||||
}
|
||||
@@ -104,7 +104,7 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor
|
||||
/**
|
||||
* Executes all SQL statements.
|
||||
*
|
||||
* @param Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
|
||||
* @param \Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
|
||||
* @param array $params The parameters.
|
||||
* @override
|
||||
*/
|
||||
|
||||
@@ -73,7 +73,7 @@ class Expr
|
||||
* Creates an ASCending order expression.
|
||||
*
|
||||
* @param $sort
|
||||
* @return OrderBy
|
||||
* @return Expr\OrderBy
|
||||
*/
|
||||
public function asc($expr)
|
||||
{
|
||||
@@ -84,7 +84,7 @@ class Expr
|
||||
* Creates a DESCending order expression.
|
||||
*
|
||||
* @param $sort
|
||||
* @return OrderBy
|
||||
* @return Expr\OrderBy
|
||||
*/
|
||||
public function desc($expr)
|
||||
{
|
||||
|
||||
@@ -39,30 +39,30 @@ class Composite extends Base
|
||||
if ($this->count() === 1) {
|
||||
return (string) $this->_parts[0];
|
||||
}
|
||||
|
||||
|
||||
$components = array();
|
||||
|
||||
|
||||
foreach ($this->_parts as $part) {
|
||||
$components[] = $this->processQueryPart($part);
|
||||
}
|
||||
|
||||
|
||||
return implode($this->_separator, $components);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private function processQueryPart($part)
|
||||
{
|
||||
$queryPart = (string) $part;
|
||||
|
||||
|
||||
if (is_object($part) && $part instanceof self && $part->count() > 1) {
|
||||
return $this->_preSeparator . $queryPart . $this->_postSeparator;
|
||||
}
|
||||
|
||||
|
||||
// Fixes DDC-1237: User may have added a where item containing nested expression (with "OR" or "AND")
|
||||
if (mb_stripos($queryPart, ' OR ') !== false || mb_stripos($queryPart, ' AND ') !== false) {
|
||||
if (stripos($queryPart, ' OR ') !== false || stripos($queryPart, ' AND ') !== false) {
|
||||
return $this->_preSeparator . $queryPart . $this->_postSeparator;
|
||||
}
|
||||
|
||||
|
||||
return $queryPart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ class ParameterTypeInferer
|
||||
{
|
||||
/**
|
||||
* Infer type of a given value, returning a compatible constant:
|
||||
* - Type (Doctrine\DBAL\Types\Type::*)
|
||||
* - Connection (Doctrine\DBAL\Connection::PARAM_*)
|
||||
* - Type (\Doctrine\DBAL\Types\Type::*)
|
||||
* - Connection (\Doctrine\DBAL\Connection::PARAM_*)
|
||||
*
|
||||
* @param mixed $value Parameter value
|
||||
*
|
||||
|
||||
@@ -75,14 +75,14 @@ class Parser
|
||||
/**
|
||||
* The lexer.
|
||||
*
|
||||
* @var Doctrine\ORM\Query\Lexer
|
||||
* @var \Doctrine\ORM\Query\Lexer
|
||||
*/
|
||||
private $_lexer;
|
||||
|
||||
/**
|
||||
* The parser result.
|
||||
*
|
||||
* @var Doctrine\ORM\Query\ParserResult
|
||||
* @var \Doctrine\ORM\Query\ParserResult
|
||||
*/
|
||||
private $_parserResult;
|
||||
|
||||
@@ -170,7 +170,7 @@ class Parser
|
||||
/**
|
||||
* Gets the lexer used by the parser.
|
||||
*
|
||||
* @return Doctrine\ORM\Query\Lexer
|
||||
* @return \Doctrine\ORM\Query\Lexer
|
||||
*/
|
||||
public function getLexer()
|
||||
{
|
||||
@@ -180,7 +180,7 @@ class Parser
|
||||
/**
|
||||
* Gets the ParserResult that is being filled with information during parsing.
|
||||
*
|
||||
* @return Doctrine\ORM\Query\ParserResult
|
||||
* @return \Doctrine\ORM\Query\ParserResult
|
||||
*/
|
||||
public function getParserResult()
|
||||
{
|
||||
@@ -1466,7 +1466,7 @@ class Parser
|
||||
/**
|
||||
* RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable
|
||||
*
|
||||
* @return Doctrine\ORM\Query\AST\RangeVariableDeclaration
|
||||
* @return \Doctrine\ORM\Query\AST\RangeVariableDeclaration
|
||||
*/
|
||||
public function RangeVariableDeclaration()
|
||||
{
|
||||
@@ -1537,7 +1537,7 @@ class Parser
|
||||
* Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression
|
||||
* ["AS"] AliasIdentificationVariable ["WITH" ConditionalExpression]
|
||||
*
|
||||
* @return Doctrine\ORM\Query\AST\Join
|
||||
* @return \Doctrine\ORM\Query\AST\Join
|
||||
*/
|
||||
public function Join()
|
||||
{
|
||||
@@ -1607,7 +1607,7 @@ class Parser
|
||||
/**
|
||||
* IndexBy ::= "INDEX" "BY" StateFieldPathExpression
|
||||
*
|
||||
* @return Doctrine\ORM\Query\AST\IndexBy
|
||||
* @return \Doctrine\ORM\Query\AST\IndexBy
|
||||
*/
|
||||
public function IndexBy()
|
||||
{
|
||||
@@ -1698,7 +1698,7 @@ class Parser
|
||||
/**
|
||||
* CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")"
|
||||
*
|
||||
* @return Doctrine\ORM\Query\AST\CoalesceExpression
|
||||
* @return \Doctrine\ORM\Query\AST\CoalesceExpression
|
||||
*/
|
||||
public function CoalesceExpression()
|
||||
{
|
||||
@@ -1722,7 +1722,7 @@ class Parser
|
||||
/**
|
||||
* NullIfExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")"
|
||||
*
|
||||
* @return Doctrine\ORM\Query\AST\ExistsExpression
|
||||
* @return \Doctrine\ORM\Query\AST\ExistsExpression
|
||||
*/
|
||||
public function NullIfExpression()
|
||||
{
|
||||
@@ -1743,7 +1743,7 @@ class Parser
|
||||
* IdentificationVariable | StateFieldPathExpression |
|
||||
* (AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable]
|
||||
*
|
||||
* @return Doctrine\ORM\Query\AST\SelectExpression
|
||||
* @return \Doctrine\ORM\Query\AST\SelectExpression
|
||||
*/
|
||||
public function SelectExpression()
|
||||
{
|
||||
@@ -1967,7 +1967,7 @@ class Parser
|
||||
/**
|
||||
* ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")"
|
||||
*
|
||||
* @return Doctrine\ORM\Query\AST\ConditionalPrimary
|
||||
* @return \Doctrine\ORM\Query\AST\ConditionalPrimary
|
||||
*/
|
||||
public function ConditionalPrimary()
|
||||
{
|
||||
|
||||
@@ -72,6 +72,11 @@ class QueryException extends \Doctrine\ORM\ORMException
|
||||
return new self("Invalid parameter: token ".$key." is not defined in the query.");
|
||||
}
|
||||
|
||||
public static function parameterTypeMissmatch()
|
||||
{
|
||||
return new self("DQL Query parameter and type numbers missmatch, but have to be exactly equal.");
|
||||
}
|
||||
|
||||
public static function invalidPathExpression($pathExpr)
|
||||
{
|
||||
return new self(
|
||||
@@ -84,7 +89,7 @@ class QueryException extends \Doctrine\ORM\ORMException
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Doctrine\ORM\Mapping\AssociationMapping $assoc
|
||||
* @param \Doctrine\ORM\Mapping\AssociationMapping $assoc
|
||||
*/
|
||||
public static function iterateWithFetchJoinCollectionNotAllowed($assoc)
|
||||
{
|
||||
@@ -135,7 +140,7 @@ class QueryException extends \Doctrine\ORM\ORMException
|
||||
"in the query."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static function instanceOfUnrelatedClass($className, $rootClass)
|
||||
{
|
||||
return new self("Cannot check if a child of '" . $rootClass . "' is instanceof '" . $className . "', " .
|
||||
|
||||
@@ -35,6 +35,11 @@ use Doctrine\DBAL\LockMode,
|
||||
*/
|
||||
class SqlWalker implements TreeWalker
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const HINT_DISTINCT = 'doctrine.distinct';
|
||||
|
||||
/**
|
||||
* @var ResultSetMapping
|
||||
*/
|
||||
@@ -57,7 +62,7 @@ class SqlWalker implements TreeWalker
|
||||
private $_em;
|
||||
|
||||
/**
|
||||
* @var Doctrine\DBAL\Connection
|
||||
* @var \Doctrine\DBAL\Connection
|
||||
*/
|
||||
private $_conn;
|
||||
|
||||
@@ -157,32 +162,24 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function getExecutor($AST)
|
||||
{
|
||||
$isDeleteStatement = $AST instanceof AST\DeleteStatement;
|
||||
$isUpdateStatement = $AST instanceof AST\UpdateStatement;
|
||||
|
||||
if ($isDeleteStatement) {
|
||||
$primaryClass = $this->_em->getClassMetadata(
|
||||
$AST->deleteClause->abstractSchemaName
|
||||
);
|
||||
|
||||
if ($primaryClass->isInheritanceTypeJoined()) {
|
||||
return new Exec\MultiTableDeleteExecutor($AST, $this);
|
||||
} else {
|
||||
return new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
|
||||
}
|
||||
} else if ($isUpdateStatement) {
|
||||
$primaryClass = $this->_em->getClassMetadata(
|
||||
$AST->updateClause->abstractSchemaName
|
||||
);
|
||||
|
||||
if ($primaryClass->isInheritanceTypeJoined()) {
|
||||
return new Exec\MultiTableUpdateExecutor($AST, $this);
|
||||
} else {
|
||||
return new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
|
||||
}
|
||||
switch (true) {
|
||||
case ($AST instanceof AST\DeleteStatement):
|
||||
$primaryClass = $this->_em->getClassMetadata($AST->deleteClause->abstractSchemaName);
|
||||
|
||||
return ($primaryClass->isInheritanceTypeJoined())
|
||||
? new Exec\MultiTableDeleteExecutor($AST, $this)
|
||||
: new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
|
||||
|
||||
case ($AST instanceof AST\UpdateStatement):
|
||||
$primaryClass = $this->_em->getClassMetadata($AST->updateClause->abstractSchemaName);
|
||||
|
||||
return ($primaryClass->isInheritanceTypeJoined())
|
||||
? new Exec\MultiTableUpdateExecutor($AST, $this)
|
||||
: new Exec\SingleTableDeleteUpdateExecutor($AST, $this);
|
||||
|
||||
default:
|
||||
return new Exec\SingleSelectExecutor($AST, $this);
|
||||
}
|
||||
|
||||
return new Exec\SingleSelectExecutor($AST, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,13 +252,10 @@ class SqlWalker implements TreeWalker
|
||||
$sql .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform)
|
||||
. ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
foreach ($class->identifier as $idField) {
|
||||
foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
|
||||
$columnName = $class->getQuotedColumnName($idField, $this->_platform);
|
||||
$sql .= $baseTableAlias . '.' . $columnName
|
||||
. ' = '
|
||||
. $tableAlias . '.' . $columnName;
|
||||
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,13 +267,11 @@ class SqlWalker implements TreeWalker
|
||||
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform)
|
||||
. ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
foreach ($class->identifier as $idField) {
|
||||
|
||||
foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
|
||||
$columnName = $class->getQuotedColumnName($idField, $this->_platform);
|
||||
$sql .= $baseTableAlias . '.' . $columnName
|
||||
. ' = '
|
||||
. $tableAlias . '.' . $columnName;
|
||||
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -529,6 +521,10 @@ class SqlWalker implements TreeWalker
|
||||
$sql = 'SELECT ' . (($selectClause->isDistinct) ? 'DISTINCT ' : '');
|
||||
$sqlSelectExpressions = array_filter(array_map(array($this, 'walkSelectExpression'), $selectClause->selectExpressions));
|
||||
|
||||
if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true && $selectClause->isDistinct) {
|
||||
$this->_query->setHint(self::HINT_DISTINCT, true);
|
||||
}
|
||||
|
||||
$addMetaColumns = ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD) &&
|
||||
$this->_query->getHydrationMode() == Query::HYDRATE_OBJECT
|
||||
||
|
||||
@@ -749,8 +745,7 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
// Ensure we got the owning side, since it has all mapping info
|
||||
$assoc = ( ! $relation['isOwningSide']) ? $targetClass->associationMappings[$relation['mappedBy']] : $relation;
|
||||
|
||||
if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true) {
|
||||
if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true && (!$this->_query->getHint(self::HINT_DISTINCT) || isset($this->_selectedClasses[$joinedDqlAlias]))) {
|
||||
if ($relation['type'] == ClassMetadata::ONE_TO_MANY || $relation['type'] == ClassMetadata::MANY_TO_MANY) {
|
||||
throw QueryException::iterateWithFetchJoinNotAllowed($assoc);
|
||||
}
|
||||
@@ -1233,67 +1228,77 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkSimpleSelectExpression($simpleSelectExpression)
|
||||
{
|
||||
$sql = '';
|
||||
$expr = $simpleSelectExpression->expression;
|
||||
$sql = ' ';
|
||||
|
||||
switch (true) {
|
||||
case ($expr instanceof AST\PathExpression):
|
||||
$sql .= $this->walkPathExpression($expr);
|
||||
break;
|
||||
|
||||
case ($expr instanceof AST\AggregateExpression):
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
|
||||
|
||||
$sql .= $this->walkAggregateExpression($expr) . ' AS dctrn__' . $alias;
|
||||
break;
|
||||
|
||||
case ($expr instanceof AST\Subselect):
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
|
||||
$sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias;
|
||||
break;
|
||||
|
||||
case ($expr instanceof AST\Functions\FunctionNode):
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
|
||||
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
|
||||
break;
|
||||
|
||||
case ($expr instanceof AST\SimpleArithmeticExpression):
|
||||
case ($expr instanceof AST\ArithmeticTerm):
|
||||
case ($expr instanceof AST\ArithmeticFactor):
|
||||
case ($expr instanceof AST\ArithmeticPrimary):
|
||||
case ($expr instanceof AST\Literal):
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
|
||||
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
|
||||
break;
|
||||
|
||||
case ($expr instanceof AST\NullIfExpression):
|
||||
case ($expr instanceof AST\CoalesceExpression):
|
||||
case ($expr instanceof AST\GeneralCaseExpression):
|
||||
case ($expr instanceof AST\SimpleCaseExpression):
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->_scalarResultCounter++;
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
|
||||
$sql .= $this->walkCaseExpression($expr) . ' AS ' . $columnAlias;
|
||||
break;
|
||||
|
||||
default: // IdentificationVariable
|
||||
$class = $this->_queryComponents[$expr]['metadata'];
|
||||
$tableAlias = $this->getSQLTableAlias($class->getTableName(), $expr);
|
||||
$sqlParts = array();
|
||||
|
||||
if ($expr instanceof AST\PathExpression) {
|
||||
$sql .= $this->walkPathExpression($expr);
|
||||
} else if ($expr instanceof AST\AggregateExpression) {
|
||||
if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
|
||||
$alias = $this->_scalarResultCounter++;
|
||||
} else {
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$sql .= $this->walkAggregateExpression($expr) . ' AS dctrn__' . $alias;
|
||||
} else if ($expr instanceof AST\Subselect) {
|
||||
if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
|
||||
$alias = $this->_scalarResultCounter++;
|
||||
} else {
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
} else if ($expr instanceof AST\Functions\FunctionNode) {
|
||||
if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
|
||||
$alias = $this->_scalarResultCounter++;
|
||||
} else {
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
} else if (
|
||||
$expr instanceof AST\SimpleArithmeticExpression ||
|
||||
$expr instanceof AST\ArithmeticTerm ||
|
||||
$expr instanceof AST\ArithmeticFactor ||
|
||||
$expr instanceof AST\ArithmeticPrimary
|
||||
) {
|
||||
if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
|
||||
$alias = $this->_scalarResultCounter++;
|
||||
} else {
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
} else {
|
||||
// IdentificationVariable
|
||||
$class = $this->_queryComponents[$expr]['metadata'];
|
||||
$tableAlias = $this->getSQLTableAlias($class->getTableName(), $expr);
|
||||
$first = true;
|
||||
|
||||
foreach ($class->identifier as $identifier) {
|
||||
if ($first) $first = false; else $sql .= ', ';
|
||||
$sql .= $tableAlias . '.' . $class->getQuotedColumnName($identifier, $this->_platform);
|
||||
}
|
||||
foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
|
||||
$sqlParts[] = $tableAlias . '.' . $columnName;
|
||||
}
|
||||
|
||||
$sql .= implode(', ', $sqlParts);
|
||||
break;
|
||||
}
|
||||
|
||||
return ' ' . $sql;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1316,25 +1321,24 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkGroupByClause($groupByClause)
|
||||
{
|
||||
$sql = '';
|
||||
$sqlParts = array();
|
||||
|
||||
foreach ($groupByClause->groupByItems AS $groupByItem) {
|
||||
if (is_string($groupByItem)) {
|
||||
foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) {
|
||||
if ($sql != '') {
|
||||
$sql .= ', ';
|
||||
}
|
||||
$groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField);
|
||||
$groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD;
|
||||
$sql .= $this->walkGroupByItem($groupByItem);
|
||||
}
|
||||
} else {
|
||||
if ($sql != '') {
|
||||
$sql .= ', ';
|
||||
}
|
||||
$sql .= $this->walkGroupByItem($groupByItem);
|
||||
if ( ! is_string($groupByItem)) {
|
||||
$sqlParts[] = $this->walkGroupByItem($groupByItem);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($this->_queryComponents[$groupByItem]['metadata']->identifier AS $idField) {
|
||||
$groupByItem = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $idField);
|
||||
$groupByItem->type = AST\PathExpression::TYPE_STATE_FIELD;
|
||||
|
||||
$sqlParts[] = $this->walkGroupByItem($groupByItem);
|
||||
}
|
||||
}
|
||||
return ' GROUP BY ' . $sql;
|
||||
|
||||
return ' GROUP BY ' . implode(', ', $sqlParts);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1356,12 +1360,11 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkDeleteClause(AST\DeleteClause $deleteClause)
|
||||
{
|
||||
$sql = 'DELETE FROM ';
|
||||
$class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName);
|
||||
$sql .= $class->getQuotedTableName($this->_platform);
|
||||
|
||||
$this->setSQLTableAlias($class->getTableName(), $class->getTableName(), $deleteClause->aliasIdentificationVariable);
|
||||
|
||||
$class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName);
|
||||
$tableName = $class->getTableName();
|
||||
$sql = 'DELETE FROM ' . $class->getQuotedTableName($this->_platform);
|
||||
|
||||
$this->setSQLTableAlias($tableName, $tableName, $deleteClause->aliasIdentificationVariable);
|
||||
$this->_rootAliases[] = $deleteClause->aliasIdentificationVariable;
|
||||
|
||||
return $sql;
|
||||
@@ -1375,17 +1378,14 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkUpdateClause($updateClause)
|
||||
{
|
||||
$sql = 'UPDATE ';
|
||||
$class = $this->_em->getClassMetadata($updateClause->abstractSchemaName);
|
||||
$sql .= $class->getQuotedTableName($this->_platform);
|
||||
|
||||
$this->setSQLTableAlias($class->getTableName(), $class->getTableName(), $updateClause->aliasIdentificationVariable);
|
||||
|
||||
$class = $this->_em->getClassMetadata($updateClause->abstractSchemaName);
|
||||
$tableName = $class->getTableName();
|
||||
$sql = 'UPDATE ' . $class->getQuotedTableName($this->_platform);
|
||||
|
||||
$this->setSQLTableAlias($tableName, $tableName, $updateClause->aliasIdentificationVariable);
|
||||
$this->_rootAliases[] = $updateClause->aliasIdentificationVariable;
|
||||
|
||||
$sql .= ' SET ' . implode(
|
||||
', ', array_map(array($this, 'walkUpdateItem'), $updateClause->updateItems)
|
||||
);
|
||||
$sql .= ' SET ' . implode(', ', array_map(array($this, 'walkUpdateItem'), $updateClause->updateItems));
|
||||
|
||||
return $sql;
|
||||
}
|
||||
@@ -1401,16 +1401,21 @@ class SqlWalker implements TreeWalker
|
||||
$useTableAliasesBefore = $this->_useSqlTableAliases;
|
||||
$this->_useSqlTableAliases = false;
|
||||
|
||||
$sql = $this->walkPathExpression($updateItem->pathExpression) . ' = ';
|
||||
|
||||
$sql = $this->walkPathExpression($updateItem->pathExpression) . ' = ';
|
||||
$newValue = $updateItem->newValue;
|
||||
|
||||
if ($newValue === null) {
|
||||
$sql .= 'NULL';
|
||||
} else if ($newValue instanceof AST\Node) {
|
||||
$sql .= $newValue->dispatch($this);
|
||||
} else {
|
||||
$sql .= $this->_conn->quote($newValue);
|
||||
switch (true) {
|
||||
case ($newValue instanceof AST\Node):
|
||||
$sql .= $newValue->dispatch($this);
|
||||
break;
|
||||
|
||||
case ($newValue === null):
|
||||
$sql .= 'NULL';
|
||||
break;
|
||||
|
||||
default:
|
||||
$sql .= $this->_conn->quote($newValue);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->_useSqlTableAliases = $useTableAliasesBefore;
|
||||
@@ -1429,7 +1434,15 @@ class SqlWalker implements TreeWalker
|
||||
$discrSql = $this->_generateDiscriminatorColumnConditionSql($this->_rootAliases);
|
||||
$condSql = $this->walkConditionalExpression($whereClause->conditionalExpression);
|
||||
|
||||
return ' WHERE ' . (( ! $discrSql) ? $condSql : '(' . $condSql . ') AND ' . $discrSql);
|
||||
if ($condSql) {
|
||||
return ' WHERE ' . (( ! $discrSql) ? $condSql : '(' . $condSql . ') AND ' . $discrSql);
|
||||
}
|
||||
|
||||
if ($discrSql) {
|
||||
return ' WHERE ' . $discrSql;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1442,11 +1455,11 @@ class SqlWalker implements TreeWalker
|
||||
{
|
||||
// Phase 2 AST optimization: Skip processment of ConditionalExpression
|
||||
// if only one ConditionalTerm is defined
|
||||
return ( ! ($condExpr instanceof AST\ConditionalExpression))
|
||||
? $this->walkConditionalTerm($condExpr)
|
||||
: implode(
|
||||
' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms)
|
||||
);
|
||||
if ( ! ($condExpr instanceof AST\ConditionalExpression)) {
|
||||
return $this->walkConditionalTerm($condExpr);
|
||||
}
|
||||
|
||||
return implode(' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1459,11 +1472,11 @@ class SqlWalker implements TreeWalker
|
||||
{
|
||||
// Phase 2 AST optimization: Skip processment of ConditionalTerm
|
||||
// if only one ConditionalFactor is defined
|
||||
return ( ! ($condTerm instanceof AST\ConditionalTerm))
|
||||
? $this->walkConditionalFactor($condTerm)
|
||||
: implode(
|
||||
' AND ', array_map(array($this, 'walkConditionalFactor'), $condTerm->conditionalFactors)
|
||||
);
|
||||
if ( ! ($condTerm instanceof AST\ConditionalTerm)) {
|
||||
return $this->walkConditionalFactor($condTerm);
|
||||
}
|
||||
|
||||
return implode(' AND ', array_map(array($this, 'walkConditionalFactor'), $condTerm->conditionalFactors));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1491,7 +1504,9 @@ class SqlWalker implements TreeWalker
|
||||
{
|
||||
if ($primary->isSimpleConditionalExpression()) {
|
||||
return $primary->simpleConditionalExpression->dispatch($this);
|
||||
} else if ($primary->isConditionalExpression()) {
|
||||
}
|
||||
|
||||
if ($primary->isConditionalExpression()) {
|
||||
$condExpr = $primary->conditionalExpression;
|
||||
|
||||
return '(' . $this->walkConditionalExpression($condExpr) . ')';
|
||||
@@ -1564,12 +1579,11 @@ class SqlWalker implements TreeWalker
|
||||
$sql .= ' AND ';
|
||||
$first = true;
|
||||
|
||||
foreach ($targetClass->identifier as $idField) {
|
||||
foreach ($targetClass->getQuotedIdentifierColumnNames($this->_platform) as $targetColumnName) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
$sql .= $targetTableAlias . '.'
|
||||
. $targetClass->getQuotedColumnName($idField, $this->_platform) . ' = ?';
|
||||
$sql .= $targetTableAlias . '.' . $targetColumnName . ' = ?';
|
||||
}
|
||||
} else { // many-to-many
|
||||
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||
@@ -1622,12 +1636,11 @@ class SqlWalker implements TreeWalker
|
||||
$sql .= ' AND ';
|
||||
$first = true;
|
||||
|
||||
foreach ($targetClass->identifier as $idField) {
|
||||
foreach ($targetClass->getQuotedIdentifierColumnNames($this->_platform) as $targetColumnName) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
$sql .= $targetTableAlias . '.'
|
||||
. $targetClass->getQuotedColumnName($idField, $this->_platform) . ' = ?';
|
||||
$sql .= $targetTableAlias . '.' . $targetColumnName . ' = ?';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1680,14 +1693,12 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkInExpression($inExpr)
|
||||
{
|
||||
$sql = $this->walkPathExpression($inExpr->pathExpression)
|
||||
$sql = $this->walkPathExpression($inExpr->pathExpression)
|
||||
. ($inExpr->not ? ' NOT' : '') . ' IN (';
|
||||
|
||||
if ($inExpr->subselect) {
|
||||
$sql .= $this->walkSubselect($inExpr->subselect);
|
||||
} else {
|
||||
$sql .= implode(', ', array_map(array($this, 'walkInParameter'), $inExpr->literals));
|
||||
}
|
||||
$sql .= ($inExpr->subselect)
|
||||
? $this->walkSubselect($inExpr->subselect)
|
||||
: implode(', ', array_map(array($this, 'walkInParameter'), $inExpr->literals));
|
||||
|
||||
$sql .= ')';
|
||||
|
||||
@@ -1755,9 +1766,9 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkInParameter($inParam)
|
||||
{
|
||||
return $inParam instanceof AST\InputParameter ?
|
||||
$this->walkInputParameter($inParam) :
|
||||
$this->walkLiteral($inParam);
|
||||
return $inParam instanceof AST\InputParameter
|
||||
? $this->walkInputParameter($inParam)
|
||||
: $this->walkLiteral($inParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1846,23 +1857,19 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkComparisonExpression($compExpr)
|
||||
{
|
||||
$sql = '';
|
||||
$leftExpr = $compExpr->leftExpression;
|
||||
$leftExpr = $compExpr->leftExpression;
|
||||
$rightExpr = $compExpr->rightExpression;
|
||||
|
||||
if ($leftExpr instanceof AST\Node) {
|
||||
$sql .= $leftExpr->dispatch($this);
|
||||
} else {
|
||||
$sql .= is_numeric($leftExpr) ? $leftExpr : $this->_conn->quote($leftExpr);
|
||||
}
|
||||
$sql = '';
|
||||
|
||||
$sql .= ($leftExpr instanceof AST\Node)
|
||||
? $leftExpr->dispatch($this)
|
||||
: (is_numeric($leftExpr) ? $leftExpr : $this->_conn->quote($leftExpr));
|
||||
|
||||
$sql .= ' ' . $compExpr->operator . ' ';
|
||||
|
||||
if ($rightExpr instanceof AST\Node) {
|
||||
$sql .= $rightExpr->dispatch($this);
|
||||
} else {
|
||||
$sql .= is_numeric($rightExpr) ? $rightExpr : $this->_conn->quote($rightExpr);
|
||||
}
|
||||
$sql .= ($rightExpr instanceof AST\Node)
|
||||
? $rightExpr->dispatch($this)
|
||||
: (is_numeric($rightExpr) ? $rightExpr : $this->_conn->quote($rightExpr));
|
||||
|
||||
return $sql;
|
||||
}
|
||||
@@ -1901,11 +1908,11 @@ class SqlWalker implements TreeWalker
|
||||
*/
|
||||
public function walkSimpleArithmeticExpression($simpleArithmeticExpr)
|
||||
{
|
||||
return ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression))
|
||||
? $this->walkArithmeticTerm($simpleArithmeticExpr)
|
||||
: implode(
|
||||
' ', array_map(array($this, 'walkArithmeticTerm'), $simpleArithmeticExpr->arithmeticTerms)
|
||||
);
|
||||
if ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression)) {
|
||||
return $this->walkArithmeticTerm($simpleArithmeticExpr);
|
||||
}
|
||||
|
||||
return implode(' ', array_map(array($this, 'walkArithmeticTerm'), $simpleArithmeticExpr->arithmeticTerms));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1928,11 +1935,11 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
// Phase 2 AST optimization: Skip processment of ArithmeticTerm
|
||||
// if only one ArithmeticFactor is defined
|
||||
return ( ! ($term instanceof AST\ArithmeticTerm))
|
||||
? $this->walkArithmeticFactor($term)
|
||||
: implode(
|
||||
' ', array_map(array($this, 'walkArithmeticFactor'), $term->arithmeticFactors)
|
||||
);
|
||||
if ( ! ($term instanceof AST\ArithmeticTerm)) {
|
||||
return $this->walkArithmeticFactor($term);
|
||||
}
|
||||
|
||||
return implode(' ', array_map(array($this, 'walkArithmeticFactor'), $term->arithmeticFactors));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1949,10 +1956,13 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
// Phase 2 AST optimization: Skip processment of ArithmeticFactor
|
||||
// if only one ArithmeticPrimary is defined
|
||||
return ( ! ($factor instanceof AST\ArithmeticFactor))
|
||||
? $this->walkArithmeticPrimary($factor)
|
||||
: ($factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : ''))
|
||||
. $this->walkArithmeticPrimary($factor->arithmeticPrimary);
|
||||
if ( ! ($factor instanceof AST\ArithmeticFactor)) {
|
||||
return $this->walkArithmeticPrimary($factor);
|
||||
}
|
||||
|
||||
$sign = $factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : '');
|
||||
|
||||
return $sign . $this->walkArithmeticPrimary($factor->arithmeticPrimary);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1965,7 +1975,9 @@ class SqlWalker implements TreeWalker
|
||||
{
|
||||
if ($primary instanceof AST\SimpleArithmeticExpression) {
|
||||
return '(' . $this->walkSimpleArithmeticExpression($primary) . ')';
|
||||
} else if ($primary instanceof AST\Node) {
|
||||
}
|
||||
|
||||
if ($primary instanceof AST\Node) {
|
||||
return $primary->dispatch($this);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ abstract class TreeWalkerAdapter implements TreeWalker
|
||||
/**
|
||||
* Retrieve Query Instance reponsible for the current walkers execution.
|
||||
*
|
||||
* @return Doctrine\ORM\Query
|
||||
* @return \Doctrine\ORM\Query
|
||||
*/
|
||||
protected function _getQuery()
|
||||
{
|
||||
@@ -65,7 +65,7 @@ abstract class TreeWalkerAdapter implements TreeWalker
|
||||
/**
|
||||
* Retrieve ParserResult
|
||||
*
|
||||
* @return Doctrine\ORM\Query\ParserResult
|
||||
* @return \Doctrine\ORM\Query\ParserResult
|
||||
*/
|
||||
protected function _getParserResult()
|
||||
{
|
||||
|
||||
@@ -50,6 +50,7 @@ class QueryBuilder
|
||||
* @var array The array of DQL parts collected.
|
||||
*/
|
||||
private $_dqlParts = array(
|
||||
'distinct' => false,
|
||||
'select' => array(),
|
||||
'from' => array(),
|
||||
'join' => array(),
|
||||
@@ -119,7 +120,7 @@ class QueryBuilder
|
||||
* For more complex expression construction, consider storing the expression
|
||||
* builder object in a local variable.
|
||||
*
|
||||
* @return Expr
|
||||
* @return Query\Expr
|
||||
*/
|
||||
public function expr()
|
||||
{
|
||||
@@ -342,8 +343,8 @@ class QueryBuilder
|
||||
* ->from('User', 'u')
|
||||
* ->where('u.id = :user_id1 OR u.id = :user_id2')
|
||||
* ->setParameters(array(
|
||||
* ':user_id1' => 1,
|
||||
* ':user_id2' => 2
|
||||
* 'user_id1' => 1,
|
||||
* 'user_id2' => 2
|
||||
* ));
|
||||
* </code>
|
||||
*
|
||||
@@ -502,6 +503,25 @@ class QueryBuilder
|
||||
return $this->add('select', new Expr\Select($selects), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a DISTINCT flag to this query.
|
||||
*
|
||||
* <code>
|
||||
* $qb = $em->createQueryBuilder()
|
||||
* ->select('u')
|
||||
* ->distinct()
|
||||
* ->from('User', 'u');
|
||||
* </code>
|
||||
*
|
||||
* @param bool
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function distinct($flag = true)
|
||||
{
|
||||
$this->_dqlParts['distinct'] = (bool) $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item that is to be returned in the query result.
|
||||
*
|
||||
@@ -973,8 +993,10 @@ class QueryBuilder
|
||||
|
||||
private function _getDQLForSelect()
|
||||
{
|
||||
$dql = 'SELECT' . $this->_getReducedDQLQueryPart('select', array('pre' => ' ', 'separator' => ', '));
|
||||
|
||||
$dql = 'SELECT'
|
||||
. ($this->_dqlParts['distinct']===true ? ' DISTINCT' : '')
|
||||
. $this->_getReducedDQLQueryPart('select', array('pre' => ' ', 'separator' => ', '));
|
||||
|
||||
$fromParts = $this->getDQLPart('from');
|
||||
$joinParts = $this->getDQLPart('join');
|
||||
$fromClauses = array();
|
||||
@@ -1082,4 +1104,4 @@ class QueryBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ EOT
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
/* @var $entityManager Doctrine\ORM\EntityManager */
|
||||
/* @var $entityManager \Doctrine\ORM\EntityManager */
|
||||
$entityManager = $this->getHelper('em')->getEntityManager();
|
||||
|
||||
$entityClassNames = $entityManager->getConfiguration()
|
||||
|
||||
@@ -189,6 +189,8 @@ public function <methodName>()
|
||||
|
||||
if ( ! $this->_isNew) {
|
||||
$this->_parseTokensInEntityFile(file_get_contents($path));
|
||||
} else {
|
||||
$this->_staticReflection[$metadata->name] = array('properties' => array(), 'methods' => array());
|
||||
}
|
||||
|
||||
if ($this->_backupExisting && file_exists($path)) {
|
||||
@@ -783,7 +785,7 @@ public function <methodName>()
|
||||
}
|
||||
|
||||
if (isset($joinColumn['onDelete'])) {
|
||||
$joinColumnAnnot[] = 'onDelete=' . ($joinColumn['onDelete'] ? 'true' : 'false');
|
||||
$joinColumnAnnot[] = 'onDelete="' . ($joinColumn['onDelete'] . '"');
|
||||
}
|
||||
|
||||
if (isset($joinColumn['onUpdate'])) {
|
||||
@@ -1061,4 +1063,4 @@ public function <methodName>()
|
||||
throw new \InvalidArgumentException('Invalid provided IdGeneratorType: ' . $type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ use Doctrine\ORM\Tools\Export\ExportException;
|
||||
|
||||
/**
|
||||
* Abstract base class which is to be used for the Exporter drivers
|
||||
* which can be found in Doctrine\ORM\Tools\Export\Driver
|
||||
* which can be found in \Doctrine\ORM\Tools\Export\Driver
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
|
||||
@@ -56,7 +56,7 @@ class SchemaTool
|
||||
* Initializes a new SchemaTool instance that uses the connection of the
|
||||
* provided EntityManager.
|
||||
*
|
||||
* @param Doctrine\ORM\EntityManager $em
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
@@ -174,7 +174,7 @@ class SchemaTool
|
||||
$discrColumnDef = $this->_getDiscriminatorColumnDefinition($class, $table);
|
||||
} else {
|
||||
// Add an ID FK column to child tables
|
||||
/* @var Doctrine\ORM\Mapping\ClassMetadata $class */
|
||||
/* @var \Doctrine\ORM\Mapping\ClassMetadata $class */
|
||||
$idMapping = $class->fieldMappings[$class->identifier[0]];
|
||||
$this->_gatherColumn($class, $idMapping, $table);
|
||||
$columnName = $class->getQuotedColumnName($class->identifier[0], $this->_platform);
|
||||
@@ -217,13 +217,13 @@ class SchemaTool
|
||||
|
||||
if (isset($class->table['indexes'])) {
|
||||
foreach ($class->table['indexes'] AS $indexName => $indexData) {
|
||||
$table->addIndex($indexData['columns'], $indexName);
|
||||
$table->addIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($class->table['uniqueConstraints'])) {
|
||||
foreach ($class->table['uniqueConstraints'] AS $indexName => $indexData) {
|
||||
$table->addUniqueIndex($indexData['columns'], $indexName);
|
||||
$table->addUniqueIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -214,6 +214,6 @@ class SchemaValidator
|
||||
$schemaTool = new SchemaTool($this->em);
|
||||
|
||||
$allMetadata = $this->em->getMetadataFactory()->getAllMetadata();
|
||||
return (count($schemaTool->getUpdateSchemaSql($allMetadata, false)) == 0);
|
||||
return (count($schemaTool->getUpdateSchemaSql($allMetadata, true)) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* Map of entities that are scheduled for dirty checking at commit time.
|
||||
* This is only used for entities with a change tracking policy of DEFERRED_EXPLICIT.
|
||||
* Keys are object ids (spl_object_hash).
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
* @todo rename: scheduledForSynchronization
|
||||
*/
|
||||
@@ -135,10 +135,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* @var array
|
||||
*/
|
||||
private $entityUpdates = array();
|
||||
|
||||
|
||||
/**
|
||||
* Any pending extra updates that have been scheduled by persisters.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $extraUpdates = array();
|
||||
@@ -176,7 +176,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
/**
|
||||
* The EntityManager that "owns" this UnitOfWork instance.
|
||||
*
|
||||
* @var Doctrine\ORM\EntityManager
|
||||
* @var \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
private $em;
|
||||
|
||||
@@ -184,7 +184,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* The calculator used to calculate the order in which changes to
|
||||
* entities need to be written to the database.
|
||||
*
|
||||
* @var Doctrine\ORM\Internal\CommitOrderCalculator
|
||||
* @var \Doctrine\ORM\Internal\CommitOrderCalculator
|
||||
*/
|
||||
private $commitOrderCalculator;
|
||||
|
||||
@@ -201,26 +201,31 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* @var array
|
||||
*/
|
||||
private $collectionPersisters = array();
|
||||
|
||||
|
||||
/**
|
||||
* The EventManager used for dispatching events.
|
||||
*
|
||||
*
|
||||
* @var EventManager
|
||||
*/
|
||||
private $evm;
|
||||
|
||||
|
||||
/**
|
||||
* Orphaned entities that are scheduled for removal.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $orphanRemovals = array();
|
||||
|
||||
//private $_readOnlyObjects = array();
|
||||
|
||||
/**
|
||||
* Read-Only objects are never evaluated
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $readOnlyObjects = array();
|
||||
|
||||
/**
|
||||
* Map of Entity Class-Names and corresponding IDs that should eager loaded when requested.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $eagerLoadingEntities = array();
|
||||
@@ -228,7 +233,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
/**
|
||||
* Initializes a new UnitOfWork instance, bound to the given EntityManager.
|
||||
*
|
||||
* @param Doctrine\ORM\EntityManager $em
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
@@ -240,15 +245,15 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* Commits the UnitOfWork, executing all operations that have been postponed
|
||||
* up to this point. The state of all managed entities will be synchronized with
|
||||
* the database.
|
||||
*
|
||||
*
|
||||
* The operations are executed in the following order:
|
||||
*
|
||||
*
|
||||
* 1) All entity insertions
|
||||
* 2) All entity updates
|
||||
* 3) All collection deletions
|
||||
* 4) All collection updates
|
||||
* 5) All entity deletions
|
||||
*
|
||||
*
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
@@ -269,12 +274,12 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$this->remove($orphan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Raise onFlush
|
||||
if ($this->evm->hasListeners(Events::onFlush)) {
|
||||
$this->evm->dispatchEvent(Events::onFlush, new Event\OnFlushEventArgs($this->em));
|
||||
}
|
||||
|
||||
|
||||
// Now we need a commit order to maintain referential integrity
|
||||
$commitOrder = $this->getCommitOrder();
|
||||
|
||||
@@ -341,7 +346,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$this->scheduledForDirtyCheck =
|
||||
$this->orphanRemovals = array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes any extra updates that have been scheduled.
|
||||
*/
|
||||
@@ -401,8 +406,13 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ( ! $class->isInheritanceTypeNone()) {
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
}
|
||||
|
||||
|
||||
$oid = spl_object_hash($entity);
|
||||
|
||||
if (isset($this->readOnlyObjects[$oid])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$actualData = array();
|
||||
foreach ($class->reflFields as $name => $refProp) {
|
||||
$value = $refProp->getValue($entity);
|
||||
@@ -415,16 +425,16 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ( ! $value instanceof Collection) {
|
||||
$value = new ArrayCollection($value);
|
||||
}
|
||||
|
||||
|
||||
$assoc = $class->associationMappings[$name];
|
||||
|
||||
|
||||
// Inject PersistentCollection
|
||||
$coll = new PersistentCollection(
|
||||
$this->em,
|
||||
$this->em->getClassMetadata($assoc['targetEntity']),
|
||||
$value
|
||||
);
|
||||
|
||||
|
||||
$coll->setOwner($entity, $assoc);
|
||||
$coll->setDirty( ! $coll->isEmpty());
|
||||
$class->reflFields[$name]->setValue($entity, $coll);
|
||||
@@ -458,7 +468,15 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$changeSet = ($isChangeTrackingNotify && isset($this->entityChangeSets[$oid])) ? $this->entityChangeSets[$oid] : array();
|
||||
|
||||
foreach ($actualData as $propName => $actualValue) {
|
||||
$orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
|
||||
if (isset($originalData[$propName])) {
|
||||
$orgValue = $originalData[$propName];
|
||||
} else if (array_key_exists($propName, $originalData)) {
|
||||
$orgValue = null;
|
||||
} else {
|
||||
// skip field, its a partially omitted one!
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($class->associationMappings[$propName])) {
|
||||
$assoc = $class->associationMappings[$propName];
|
||||
if ($assoc['type'] & ClassMetadata::TO_ONE && $orgValue !== $actualValue) {
|
||||
@@ -528,7 +546,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
foreach ($entitiesToProcess as $entity) {
|
||||
// Ignore uninitialized proxy objects
|
||||
if (/* $entity is readOnly || */ $entity instanceof Proxy && ! $entity->__isInitialized__) {
|
||||
if ($entity instanceof Proxy && ! $entity->__isInitialized__) {
|
||||
continue;
|
||||
}
|
||||
// Only MANAGED entities that are NOT SCHEDULED FOR INSERTION are processed here.
|
||||
@@ -620,16 +638,16 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
$this->scheduleForInsert($entity);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Computes the changeset of an individual entity, independently of the
|
||||
* computeChangeSets() routine that is used at the beginning of a UnitOfWork#commit().
|
||||
*
|
||||
*
|
||||
* The passed entity must be a managed entity. If the entity already has a change set
|
||||
* because this method is invoked during a commit cycle then the change sets are added.
|
||||
* whereby changes detected in this method prevail.
|
||||
*
|
||||
*
|
||||
* @ignore
|
||||
* @param ClassMetadata $class The class descriptor of the entity.
|
||||
* @param object $entity The entity for which to (re)calculate the change set.
|
||||
@@ -638,11 +656,11 @@ class UnitOfWork implements PropertyChangedListener
|
||||
public function recomputeSingleEntityChangeSet($class, $entity)
|
||||
{
|
||||
$oid = spl_object_hash($entity);
|
||||
|
||||
|
||||
if ( ! isset($this->entityStates[$oid]) || $this->entityStates[$oid] != self::STATE_MANAGED) {
|
||||
throw new InvalidArgumentException('Entity must be managed.');
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Just return if changetracking policy is NOTIFY?
|
||||
if ($class->isChangeTrackingNotify()) {
|
||||
return;
|
||||
@@ -682,19 +700,19 @@ class UnitOfWork implements PropertyChangedListener
|
||||
/**
|
||||
* Executes all entity insertions for entities of the specified type.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
*/
|
||||
private function executeInserts($class)
|
||||
{
|
||||
$className = $class->name;
|
||||
$persister = $this->getEntityPersister($className);
|
||||
|
||||
|
||||
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postPersist]);
|
||||
$hasListeners = $this->evm->hasListeners(Events::postPersist);
|
||||
if ($hasLifecycleCallbacks || $hasListeners) {
|
||||
$entities = array();
|
||||
}
|
||||
|
||||
|
||||
foreach ($this->entityInsertions as $oid => $entity) {
|
||||
if (get_class($entity) === $className) {
|
||||
$persister->addInsert($entity);
|
||||
@@ -719,7 +737,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$this->addToIdentityMap($entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($hasLifecycleCallbacks || $hasListeners) {
|
||||
foreach ($entities as $entity) {
|
||||
if ($hasLifecycleCallbacks) {
|
||||
@@ -735,7 +753,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
/**
|
||||
* Executes all entity updates for entities of the specified type.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
*/
|
||||
private function executeUpdates($class)
|
||||
{
|
||||
@@ -746,15 +764,15 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$hasPreUpdateListeners = $this->evm->hasListeners(Events::preUpdate);
|
||||
$hasPostUpdateLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postUpdate]);
|
||||
$hasPostUpdateListeners = $this->evm->hasListeners(Events::postUpdate);
|
||||
|
||||
|
||||
foreach ($this->entityUpdates as $oid => $entity) {
|
||||
if (get_class($entity) == $className || $entity instanceof Proxy && get_parent_class($entity) == $className) {
|
||||
|
||||
|
||||
if ($hasPreUpdateLifecycleCallbacks) {
|
||||
$class->invokeLifecycleCallbacks(Events::preUpdate, $entity);
|
||||
$this->recomputeSingleEntityChangeSet($class, $entity);
|
||||
}
|
||||
|
||||
|
||||
if ($hasPreUpdateListeners) {
|
||||
$this->evm->dispatchEvent(Events::preUpdate, new Event\PreUpdateEventArgs(
|
||||
$entity, $this->em, $this->entityChangeSets[$oid])
|
||||
@@ -765,7 +783,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$persister->update($entity);
|
||||
}
|
||||
unset($this->entityUpdates[$oid]);
|
||||
|
||||
|
||||
if ($hasPostUpdateLifecycleCallbacks) {
|
||||
$class->invokeLifecycleCallbacks(Events::postUpdate, $entity);
|
||||
}
|
||||
@@ -779,16 +797,16 @@ class UnitOfWork implements PropertyChangedListener
|
||||
/**
|
||||
* Executes all entity deletions for entities of the specified type.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
*/
|
||||
private function executeDeletions($class)
|
||||
{
|
||||
$className = $class->name;
|
||||
$persister = $this->getEntityPersister($className);
|
||||
|
||||
|
||||
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postRemove]);
|
||||
$hasListeners = $this->evm->hasListeners(Events::postRemove);
|
||||
|
||||
|
||||
foreach ($this->entityDeletions as $oid => $entity) {
|
||||
if (get_class($entity) == $className || $entity instanceof Proxy && get_parent_class($entity) == $className) {
|
||||
$persister->delete($entity);
|
||||
@@ -829,16 +847,16 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$this->entityDeletions
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$calc = $this->getCommitOrderCalculator();
|
||||
|
||||
|
||||
// See if there are any new classes in the changeset, that are not in the
|
||||
// commit order graph yet (dont have a node).
|
||||
|
||||
// TODO: Can we know the know the possible $newNodes based on something more efficient? IdentityMap?
|
||||
$newNodes = array();
|
||||
foreach ($entityChangeSet as $oid => $entity) {
|
||||
$className = get_class($entity);
|
||||
$className = get_class($entity);
|
||||
if ( ! $calc->hasClass($className)) {
|
||||
$class = $this->em->getClassMetadata($className);
|
||||
$calc->addClass($class);
|
||||
@@ -853,6 +871,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
|
||||
if ( ! $calc->hasClass($targetClass->name)) {
|
||||
$calc->addClass($targetClass);
|
||||
$newNodes[] = $targetClass;
|
||||
}
|
||||
$calc->addDependency($targetClass, $class);
|
||||
// If the target class has mapped subclasses,
|
||||
@@ -931,14 +950,14 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$this->entityUpdates[$oid] = $entity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Schedules an extra update that will be executed immediately after the
|
||||
* regular entity updates within the currently running commit cycle.
|
||||
*
|
||||
*
|
||||
* Extra updates for entities are stored as (entity, changeset) tuples.
|
||||
*
|
||||
*
|
||||
* @ignore
|
||||
* @param object $entity The entity for which to schedule an extra update.
|
||||
* @param array $changeset The changeset of the entity (what to update).
|
||||
@@ -976,13 +995,13 @@ class UnitOfWork implements PropertyChangedListener
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Schedules an entity for deletion.
|
||||
*
|
||||
*
|
||||
* @param object $entity
|
||||
*/
|
||||
public function scheduleForDelete($entity)
|
||||
{
|
||||
$oid = spl_object_hash($entity);
|
||||
|
||||
|
||||
if (isset($this->entityInsertions[$oid])) {
|
||||
if ($this->isInIdentityMap($entity)) {
|
||||
$this->removeFromIdentityMap($entity);
|
||||
@@ -1020,7 +1039,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
/**
|
||||
* Checks whether an entity is scheduled for insertion, update or deletion.
|
||||
*
|
||||
*
|
||||
* @param $entity
|
||||
* @return boolean
|
||||
*/
|
||||
@@ -1205,7 +1224,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ($idHash === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return isset($this->identityMap[$classMetadata->rootEntityName][$idHash]);
|
||||
}
|
||||
|
||||
@@ -1236,7 +1255,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
/**
|
||||
* Persists an entity as part of the current unit of work.
|
||||
*
|
||||
*
|
||||
* This method is internally called during persist() cascades as it tracks
|
||||
* the already visited entities to prevent infinite recursions.
|
||||
*
|
||||
@@ -1314,8 +1333,8 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
$visited[$oid] = $entity; // mark visited
|
||||
|
||||
// Cascade first, because scheduleForDelete() removes the entity from the identity map, which
|
||||
|
||||
// Cascade first, because scheduleForDelete() removes the entity from the identity map, which
|
||||
// can cause problems when a lazy proxy has to be initialized for the cascade operation.
|
||||
$this->cascadeRemove($entity, $visited);
|
||||
|
||||
@@ -1399,7 +1418,20 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$managedCopy = $class->newInstance();
|
||||
$this->persistNew($class, $managedCopy);
|
||||
} else {
|
||||
$managedCopy = $this->tryGetById($id, $class->rootEntityName);
|
||||
$flatId = $id;
|
||||
if ($class->containsForeignIdentifier) {
|
||||
// convert foreign identifiers into scalar foreign key
|
||||
// values to avoid object to string conversion failures.
|
||||
foreach ($id as $idField => $idValue) {
|
||||
if (isset($class->associationMappings[$idField])) {
|
||||
$targetClassMetadata = $this->em->getClassMetadata($class->associationMappings[$idField]['targetEntity']);
|
||||
$associatedId = $this->getEntityIdentifier($idValue);
|
||||
$flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$managedCopy = $this->tryGetById($flatId, $class->rootEntityName);
|
||||
if ($managedCopy) {
|
||||
// We have the entity in-memory already, just make sure its not removed.
|
||||
if ($this->getEntityState($managedCopy) == self::STATE_REMOVED) {
|
||||
@@ -1408,7 +1440,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
} else {
|
||||
// We need to fetch the managed copy in order to merge.
|
||||
$managedCopy = $this->em->find($class->name, $id);
|
||||
$managedCopy = $this->em->find($class->name, $flatId);
|
||||
}
|
||||
|
||||
if ($managedCopy === null) {
|
||||
@@ -1421,6 +1453,15 @@ class UnitOfWork implements PropertyChangedListener
|
||||
} else {
|
||||
throw new EntityNotFoundException;
|
||||
}
|
||||
|
||||
$managedCopy = $this->newInstance($class);
|
||||
$class->setIdentifierValues($managedCopy, $id);
|
||||
|
||||
$this->persistNew($class, $managedCopy);
|
||||
} else {
|
||||
if ($managedCopy instanceof Proxy && ! $managedCopy->__isInitialized__) {
|
||||
$managedCopy->__load();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1449,15 +1490,18 @@ class UnitOfWork implements PropertyChangedListener
|
||||
// do not merge fields marked lazy that have not been fetched.
|
||||
continue;
|
||||
} else if ( ! $assoc2['isCascadeMerge']) {
|
||||
if ($this->getEntityState($other, self::STATE_DETACHED) == self::STATE_MANAGED) {
|
||||
$prop->setValue($managedCopy, $other);
|
||||
} else {
|
||||
if ($this->getEntityState($other, self::STATE_DETACHED) !== self::STATE_MANAGED) {
|
||||
$targetClass = $this->em->getClassMetadata($assoc2['targetEntity']);
|
||||
$id = $targetClass->getIdentifierValues($other);
|
||||
$proxy = $this->em->getProxyFactory()->getProxy($assoc2['targetEntity'], $id);
|
||||
$prop->setValue($managedCopy, $proxy);
|
||||
$this->registerManaged($proxy, $id, array());
|
||||
$relatedId = $targetClass->getIdentifierValues($other);
|
||||
|
||||
if ($targetClass->subClasses) {
|
||||
$other = $this->em->find($targetClass->name, $relatedId);
|
||||
} else {
|
||||
$other = $this->em->getProxyFactory()->getProxy($assoc2['targetEntity'], $relatedId);
|
||||
$this->registerManaged($other, $relatedId, array());
|
||||
}
|
||||
}
|
||||
$prop->setValue($managedCopy, $other);
|
||||
}
|
||||
} else {
|
||||
$mergeCol = $prop->getValue($entity);
|
||||
@@ -1520,7 +1564,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
return $managedCopy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detaches an entity from the persistence management. It's persistence will
|
||||
* no longer be managed by Doctrine.
|
||||
@@ -1532,10 +1576,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$visited = array();
|
||||
$this->doDetach($entity, $visited);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes a detach operation on the given entity.
|
||||
*
|
||||
*
|
||||
* @param object $entity
|
||||
* @param array $visited
|
||||
*/
|
||||
@@ -1547,7 +1591,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
$visited[$oid] = $entity; // mark visited
|
||||
|
||||
|
||||
switch ($this->getEntityState($entity, self::STATE_DETACHED)) {
|
||||
case self::STATE_MANAGED:
|
||||
if ($this->isInIdentityMap($entity)) {
|
||||
@@ -1561,14 +1605,14 @@ class UnitOfWork implements PropertyChangedListener
|
||||
case self::STATE_DETACHED:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$this->cascadeDetach($entity, $visited);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refreshes the state of the given entity from the database, overwriting
|
||||
* any local, unpersisted changes.
|
||||
*
|
||||
*
|
||||
* @param object $entity The entity to refresh.
|
||||
* @throws InvalidArgumentException If the entity is not MANAGED.
|
||||
*/
|
||||
@@ -1577,10 +1621,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$visited = array();
|
||||
$this->doRefresh($entity, $visited);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes a refresh operation on an entity.
|
||||
*
|
||||
*
|
||||
* @param object $entity The entity to refresh.
|
||||
* @param array $visited The already visited entities during cascades.
|
||||
* @throws InvalidArgumentException If the entity is not MANAGED.
|
||||
@@ -1603,10 +1647,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
} else {
|
||||
throw new InvalidArgumentException("Entity is not MANAGED.");
|
||||
}
|
||||
|
||||
|
||||
$this->cascadeRefresh($entity, $visited);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cascades a refresh operation to associated entities.
|
||||
*
|
||||
@@ -1634,7 +1678,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cascades a detach operation to associated entities.
|
||||
*
|
||||
@@ -1710,7 +1754,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ( ! $assoc['isCascadePersist']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
|
||||
if (($relatedEntities instanceof Collection || is_array($relatedEntities))) {
|
||||
if ($relatedEntities instanceof PersistentCollection) {
|
||||
@@ -1739,11 +1783,11 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ( ! $assoc['isCascadeRemove']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if ($entity instanceof Proxy && !$entity->__isInitialized__) {
|
||||
$entity->__load();
|
||||
}
|
||||
|
||||
|
||||
$relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
|
||||
if ($relatedEntities instanceof Collection || is_array($relatedEntities)) {
|
||||
// If its a PersistentCollection initialization is intended! No unwrap!
|
||||
@@ -1768,7 +1812,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if ($this->getEntityState($entity, self::STATE_DETACHED) != self::STATE_MANAGED) {
|
||||
throw new InvalidArgumentException("Entity is not MANAGED.");
|
||||
}
|
||||
|
||||
|
||||
$entityName = get_class($entity);
|
||||
$class = $this->em->getClassMetadata($entityName);
|
||||
|
||||
@@ -1788,7 +1832,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
if (!$this->em->getConnection()->isTransactionActive()) {
|
||||
throw TransactionRequiredException::transactionRequired();
|
||||
}
|
||||
|
||||
|
||||
$oid = spl_object_hash($entity);
|
||||
|
||||
$this->getEntityPersister($class->name)->lock(
|
||||
@@ -1801,7 +1845,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
/**
|
||||
* Gets the CommitOrderCalculator used by the UnitOfWork to order commits.
|
||||
*
|
||||
* @return Doctrine\ORM\Internal\CommitOrderCalculator
|
||||
* @return \Doctrine\ORM\Internal\CommitOrderCalculator
|
||||
*/
|
||||
public function getCommitOrderCalculator()
|
||||
{
|
||||
@@ -1837,13 +1881,13 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$this->evm->dispatchEvent(Events::onClear, new Event\OnClearEventArgs($this->em));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Schedules an orphaned entity for removal. The remove() operation will be
|
||||
* invoked on that entity at the beginning of the next commit of this
|
||||
* UnitOfWork.
|
||||
*
|
||||
*
|
||||
* @ignore
|
||||
* @param object $entity
|
||||
*/
|
||||
@@ -1851,7 +1895,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
{
|
||||
$this->orphanRemovals[spl_object_hash($entity)] = $entity;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Schedules a complete collection for removal when this UnitOfWork commits.
|
||||
@@ -1880,7 +1924,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* @param array $hints Any hints to account for during reconstitution/lookup of the entity.
|
||||
* @return object The managed entity instance.
|
||||
* @internal Highly performance-sensitive method.
|
||||
*
|
||||
*
|
||||
* @todo Rename: getOrCreateEntity
|
||||
*/
|
||||
public function createEntity($className, array $data, &$hints = array())
|
||||
@@ -1906,8 +1950,8 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
$id = array($class->identifier[0] => $idHash);
|
||||
}
|
||||
|
||||
if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
|
||||
|
||||
if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
|
||||
$entity = $this->identityMap[$class->rootEntityName][$idHash];
|
||||
$oid = spl_object_hash($entity);
|
||||
if ($entity instanceof Proxy && ! $entity->__isInitialized__) {
|
||||
@@ -1918,6 +1962,11 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
} else {
|
||||
$overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
|
||||
|
||||
// If only a specific entity is set to refresh, check that it's the one
|
||||
if(isset($hints[Query::HINT_REFRESH_ENTITY])) {
|
||||
$overrideLocalValues = $hints[Query::HINT_REFRESH_ENTITY] === $entity;
|
||||
}
|
||||
}
|
||||
|
||||
if ($overrideLocalValues) {
|
||||
@@ -1945,12 +1994,12 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
// Loading the entity right here, if its in the eager loading map get rid of it there.
|
||||
unset($this->eagerLoadingEntities[$class->rootEntityName][$idHash]);
|
||||
|
||||
|
||||
// Properly initialize any unfetched associations, if partial objects are not allowed.
|
||||
if ( ! isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) {
|
||||
foreach ($class->associationMappings as $field => $assoc) {
|
||||
// Check if the association is not among the fetch-joined associations already.
|
||||
if (isset($hints['fetched'][$className][$field])) {
|
||||
if (isset($hints['fetchAlias']) && isset($hints['fetched'][$hints['fetchAlias']][$field])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1986,7 +2035,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$relatedIdHash = implode(' ', $associatedId);
|
||||
if (isset($this->identityMap[$targetClass->rootEntityName][$relatedIdHash])) {
|
||||
$newValue = $this->identityMap[$targetClass->rootEntityName][$relatedIdHash];
|
||||
|
||||
|
||||
// if this is an uninitialized proxy, we are deferring eager loads,
|
||||
// this association is marked as eager fetch, and its an uninitialized proxy (wtf!)
|
||||
// then we cann append this entity for eager loading!
|
||||
@@ -1995,7 +2044,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
!$targetClass->isIdentifierComposite &&
|
||||
$newValue instanceof Proxy &&
|
||||
$newValue->__isInitialized__ === false) {
|
||||
|
||||
|
||||
$this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId);
|
||||
}
|
||||
} else {
|
||||
@@ -2031,7 +2080,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
$this->originalEntityData[$oid][$field] = $newValue;
|
||||
$class->reflFields[$field]->setValue($entity, $newValue);
|
||||
|
||||
|
||||
if ($assoc['inversedBy'] && $assoc['type'] & ClassMetadata::ONE_TO_ONE) {
|
||||
$inverseAssoc = $targetClass->associationMappings[$assoc['inversedBy']];
|
||||
$targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($newValue, $entity);
|
||||
@@ -2061,7 +2110,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//TODO: These should be invoked later, after hydration, because associations may not yet be loaded here.
|
||||
if (isset($class->lifecycleCallbacks[Events::postLoad])) {
|
||||
$class->invokeLifecycleCallbacks(Events::postLoad, $entity);
|
||||
@@ -2088,7 +2137,11 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
foreach ($eagerLoadingEntities AS $entityName => $ids) {
|
||||
$class = $this->em->getClassMetadata($entityName);
|
||||
$this->getEntityPersister($entityName)->loadAll(array_combine($class->identifier, array(array_values($ids))));
|
||||
if ($ids) {
|
||||
$this->getEntityPersister($entityName)->loadAll(
|
||||
array_combine($class->identifier, array(array_values($ids)))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2138,7 +2191,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@@ -2171,7 +2224,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* @return array The identifier values.
|
||||
*/
|
||||
public function getEntityIdentifier($entity)
|
||||
{
|
||||
{
|
||||
return $this->entityIdentifiers[spl_object_hash($entity)];
|
||||
}
|
||||
|
||||
@@ -2234,7 +2287,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* Gets the EntityPersister for an Entity.
|
||||
*
|
||||
* @param string $entityName The name of the Entity.
|
||||
* @return Doctrine\ORM\Persisters\AbstractEntityPersister
|
||||
* @return \Doctrine\ORM\Persisters\AbstractEntityPersister
|
||||
*/
|
||||
public function getEntityPersister($entityName)
|
||||
{
|
||||
@@ -2332,27 +2385,27 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
/**
|
||||
* Gets the currently scheduled entity insertions in this UnitOfWork.
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getScheduledEntityInsertions()
|
||||
{
|
||||
return $this->entityInsertions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the currently scheduled entity updates in this UnitOfWork.
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getScheduledEntityUpdates()
|
||||
{
|
||||
return $this->entityUpdates;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the currently scheduled entity deletions in this UnitOfWork.
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getScheduledEntityDeletions()
|
||||
@@ -2379,10 +2432,10 @@ class UnitOfWork implements PropertyChangedListener
|
||||
{
|
||||
return $this->collectionUpdates;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper method to initialize a lazy loading proxy or persistent collection.
|
||||
*
|
||||
*
|
||||
* @param object
|
||||
* @return void
|
||||
*/
|
||||
@@ -2394,15 +2447,48 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$obj->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper method to show an object as string.
|
||||
*
|
||||
*
|
||||
* @param object $obj
|
||||
* @return string
|
||||
* @return string
|
||||
*/
|
||||
private static function objToStr($obj)
|
||||
{
|
||||
return method_exists($obj, '__toString') ? (string)$obj : get_class($obj).'@'.spl_object_hash($obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks an entity as read-only so that it will not be considered for updates during UnitOfWork#commit().
|
||||
*
|
||||
* This operation cannot be undone as some parts of the UnitOfWork now keep gathering information
|
||||
* on this object that might be necessary to perform a correct udpate.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @param $object
|
||||
* @return void
|
||||
*/
|
||||
public function markReadOnly($object)
|
||||
{
|
||||
if ( ! is_object($object) || ! $this->isInIdentityMap($object)) {
|
||||
throw new InvalidArgumentException("Managed entity required");
|
||||
}
|
||||
$this->readOnlyObjects[spl_object_hash($object)] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this entity read only?
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @param $object
|
||||
* @return void
|
||||
*/
|
||||
public function isReadOnly($object)
|
||||
{
|
||||
if ( ! is_object($object) ) {
|
||||
throw new InvalidArgumentException("Managed entity required");
|
||||
}
|
||||
return isset($this->readOnlyObjects[spl_object_hash($object)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class Version
|
||||
/**
|
||||
* Current Doctrine Version
|
||||
*/
|
||||
const VERSION = '2.1.2';
|
||||
const VERSION = '2.1.6';
|
||||
|
||||
/**
|
||||
* Compares a Doctrine version with the current one.
|
||||
|
||||
1
lib/vendor/doctrine-build-common
vendored
Submodule
1
lib/vendor/doctrine-build-common
vendored
Submodule
Submodule lib/vendor/doctrine-build-common added at c9ff83d716
2
lib/vendor/doctrine-common
vendored
2
lib/vendor/doctrine-common
vendored
Submodule lib/vendor/doctrine-common updated: b385ca7708...b886898821
2
lib/vendor/doctrine-dbal
vendored
2
lib/vendor/doctrine-dbal
vendored
Submodule lib/vendor/doctrine-dbal updated: e0b69790ab...148a049df4
@@ -7,7 +7,11 @@ namespace Doctrine\Tests\Models\Company;
|
||||
* @Table(name="company_contracts")
|
||||
* @InheritanceType("SINGLE_TABLE")
|
||||
* @DiscriminatorColumn(name="discr", type="string")
|
||||
* @DiscriminatorMap({"fix" = "CompanyFixContract", "flexible" = "CompanyFlexContract", "flexultra" = "CompanyFlexUltraContract"})
|
||||
* @DiscriminatorMap({
|
||||
* "fix" = "CompanyFixContract",
|
||||
* "flexible" = "CompanyFlexContract",
|
||||
* "flexultra" = "CompanyFlexUltraContract"
|
||||
* })
|
||||
*/
|
||||
abstract class CompanyContract
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ class DDC117Article
|
||||
{
|
||||
/** @Id @Column(type="integer", name="article_id") @GeneratedValue */
|
||||
private $id;
|
||||
|
||||
/** @Column */
|
||||
private $title;
|
||||
|
||||
|
||||
@@ -863,7 +863,6 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
public function testGetPartialReferenceToUpdateObjectWithoutLoadingIt()
|
||||
{
|
||||
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
|
||||
$user = new CmsUser();
|
||||
$user->username = "beberlei";
|
||||
$user->name = "Benjamin E.";
|
||||
@@ -882,7 +881,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$this->assertEquals('Stephan', $this->_em->find(get_class($user), $userId)->name);
|
||||
$this->assertEquals('Benjamin E.', $this->_em->find(get_class($user), $userId)->name);
|
||||
}
|
||||
|
||||
public function testMergePersistsNewEntities()
|
||||
|
||||
@@ -45,7 +45,7 @@ class CompositePrimaryKeyTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$poi = $this->_em->find('Doctrine\Tests\Models\Navigation\NavPointOfInterest', array('lat' => 100, 'long' => 200));
|
||||
|
||||
$this->assertType('Doctrine\Tests\Models\Navigation\NavPointOfInterest', $poi);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Navigation\NavPointOfInterest', $poi);
|
||||
$this->assertEquals(100, $poi->getLat());
|
||||
$this->assertEquals(200, $poi->getLong());
|
||||
$this->assertEquals('Brandenburger Tor', $poi->getName());
|
||||
|
||||
@@ -54,7 +54,30 @@ class DefaultValuesTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals($userId, $a2->getUser()->getId());
|
||||
$this->assertEquals('Poweruser', $a2->getUser()->type);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1386
|
||||
*/
|
||||
public function testGetPartialReferenceWithDefaultValueNotEvalutedInFlush()
|
||||
{
|
||||
$user = new DefaultValueUser;
|
||||
$user->name = 'romanb';
|
||||
$user->type = 'Normaluser';
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$user = $this->_em->getPartialReference('Doctrine\Tests\ORM\Functional\DefaultValueUser', $user->id);
|
||||
$this->assertTrue($this->_em->getUnitOfWork()->isReadOnly($user));
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$user = $this->_em->find('Doctrine\Tests\ORM\Functional\DefaultValueUser', $user->id);
|
||||
|
||||
$this->assertEquals('Normaluser', $user->type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -244,7 +244,7 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$repos = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsAddress');
|
||||
$address = $repos->findOneBy(array('user' => $userId));
|
||||
|
||||
$this->assertType('Doctrine\Tests\Models\CMS\CmsAddress', $address);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress', $address);
|
||||
$this->assertEquals($addressId, $address->id);
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$repos = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsAddress');
|
||||
$address = $repos->findOneByUser($userId);
|
||||
|
||||
$this->assertType('Doctrine\Tests\Models\CMS\CmsAddress', $address);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress', $address);
|
||||
$this->assertEquals($addressId, $address->id);
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$query = $repos->createNamedQuery('all');
|
||||
|
||||
$this->assertType('Doctrine\ORM\Query', $query);
|
||||
$this->assertInstanceOf('Doctrine\ORM\Query', $query);
|
||||
$this->assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $query->getDQL());
|
||||
}
|
||||
|
||||
@@ -355,5 +355,16 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertSame($usersAsc[0], $usersDesc[1]);
|
||||
$this->assertSame($usersAsc[1], $usersDesc[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1500
|
||||
*/
|
||||
public function testInvalidOrientation()
|
||||
{
|
||||
$this->setExpectedException('Doctrine\ORM\ORMException', 'Invalid order by orientation specified for Doctrine\Tests\Models\CMS\CmsUser#username');
|
||||
|
||||
$repo = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
|
||||
$repo->findBy(array('status' => 'test'), array('username' => 'INVALID'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup');
|
||||
$class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
|
||||
|
||||
|
||||
|
||||
$this->loadFixture();
|
||||
}
|
||||
|
||||
@@ -137,9 +137,9 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
$this->assertFalse($user->groups->isInitialized(), "Pre-Condition: Collection is not initialized.");
|
||||
|
||||
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
|
||||
|
||||
$someGroups = $user->groups->slice(0, 2);
|
||||
|
||||
$this->assertContainsOnly('Doctrine\Tests\Models\CMS\CmsGroup', $someGroups);
|
||||
@@ -225,7 +225,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertFalse($user->articles->isInitialized(), "Pre-Condition: Collection is not initialized.");
|
||||
|
||||
$article = $this->_em->find('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId);
|
||||
|
||||
|
||||
$queryCount = $this->getCurrentQueryCount();
|
||||
$this->assertTrue($user->articles->contains($article));
|
||||
$this->assertFalse($user->articles->isInitialized(), "Post-Condition: Collection is not initialized.");
|
||||
@@ -304,6 +304,49 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertFalse($user->groups->isInitialized(), "Post-Condition: Collection is not initialized.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1399
|
||||
*/
|
||||
public function testCountAfterAddThenFlush()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
|
||||
$newGroup = new \Doctrine\Tests\Models\CMS\CmsGroup();
|
||||
$newGroup->name = "Test4";
|
||||
|
||||
$user->addGroup($newGroup);
|
||||
$this->_em->persist($newGroup);
|
||||
|
||||
$this->assertFalse($user->groups->isInitialized());
|
||||
$this->assertEquals(4, count($user->groups));
|
||||
$this->assertFalse($user->groups->isInitialized());
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertEquals(4, count($user->groups));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1462
|
||||
*/
|
||||
public function testSliceOnDirtyCollection()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
/* @var $user CmsUser */
|
||||
|
||||
$newGroup = new \Doctrine\Tests\Models\CMS\CmsGroup();
|
||||
$newGroup->name = "Test4";
|
||||
|
||||
$user->addGroup($newGroup);
|
||||
$this->_em->persist($newGroup);
|
||||
|
||||
$qc = $this->getCurrentQueryCount();
|
||||
$groups = $user->groups->slice(0, 10);
|
||||
|
||||
$this->assertEquals(4, count($groups));
|
||||
$this->assertEquals($qc + 1, $this->getCurrentQueryCount());
|
||||
}
|
||||
|
||||
private function loadFixture()
|
||||
{
|
||||
$user1 = new \Doctrine\Tests\Models\CMS\CmsUser();
|
||||
@@ -364,7 +407,7 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->_em->persist($article1);
|
||||
$this->_em->persist($article2);
|
||||
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
@@ -38,9 +38,10 @@ class MappedSuperclassTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$cleanFile = $this->_em->find(get_class($file), $file->getId());
|
||||
|
||||
$this->assertType('Doctrine\Tests\Models\DirectoryTree\Directory', $cleanFile->getParent());
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\DirectoryTree\Directory', $cleanFile->getParent());
|
||||
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $cleanFile->getParent());
|
||||
$this->assertEquals($directory->getId(), $cleanFile->getParent()->getId());
|
||||
$this->assertType('Doctrine\Tests\Models\DirectoryTree\Directory', $cleanFile->getParent()->getParent());
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\DirectoryTree\Directory', $cleanFile->getParent()->getParent());
|
||||
$this->assertEquals($root->getId(), $cleanFile->getParent()->getParent()->getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,46 +13,63 @@ require_once __DIR__ . '/../../TestInit.php';
|
||||
*/
|
||||
class OneToManyOrphanRemovalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected $userId;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->useModelSet('cms');
|
||||
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testOrphanRemoval()
|
||||
{
|
||||
|
||||
$user = new CmsUser;
|
||||
$user->status = 'dev';
|
||||
$user->username = 'romanb';
|
||||
$user->name = 'Roman B.';
|
||||
|
||||
|
||||
$phone = new CmsPhonenumber;
|
||||
$phone->phonenumber = '123456';
|
||||
|
||||
|
||||
$user->addPhonenumber($phone);
|
||||
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
$userId = $user->getId();
|
||||
|
||||
|
||||
$this->userId = $user->getId();
|
||||
$this->_em->clear();
|
||||
|
||||
$userProxy = $this->_em->getReference('Doctrine\Tests\Models\CMS\CmsUser', $userId);
|
||||
|
||||
}
|
||||
|
||||
public function testOrphanRemoval()
|
||||
{
|
||||
$userProxy = $this->_em->getReference('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
|
||||
$this->_em->remove($userProxy);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$query = $this->_em->createQuery('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u');
|
||||
$result = $query->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(0, count($result), 'CmsUser should be removed by EntityManager');
|
||||
|
||||
|
||||
$query = $this->_em->createQuery('SELECT p FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p');
|
||||
$result = $query->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(0, count($result), 'CmsPhonenumber should be removed by orphanRemoval');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1496
|
||||
*/
|
||||
public function testOrphanRemovalUnitializedCollection()
|
||||
{
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
|
||||
|
||||
$user->phonenumbers->clear();
|
||||
$this->_em->flush();
|
||||
|
||||
$query = $this->_em->createQuery('SELECT p FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p');
|
||||
$result = $query->getResult();
|
||||
|
||||
$this->assertEquals(0, count($result), 'CmsPhonenumber should be removed by orphanRemoval');
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,14 @@ class OneToManyUnidirectionalAssociationTest extends \Doctrine\Tests\OrmFunction
|
||||
$this->_em->persist($routeA);
|
||||
$this->_em->persist($routeB);
|
||||
|
||||
$this->setExpectedException('Exception'); // depends on the underyling Database Driver
|
||||
$this->_em->flush(); // Exception
|
||||
$exceptionThrown = false;
|
||||
try {
|
||||
// exception depending on the underyling Database Driver
|
||||
$this->_em->flush();
|
||||
} catch(\Exception $e) {
|
||||
$exceptionThrown = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($exceptionThrown, "The underlying database driver throws an exception.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@ require_once __DIR__ . '/../../TestInit.php';
|
||||
class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp() {
|
||||
if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
|
||||
$this->markTestSkipped('Test not compatible with 2.2 common');
|
||||
}
|
||||
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
}
|
||||
@@ -86,7 +90,7 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->getConfiguration()->setQueryCacheImpl(new ArrayCache());
|
||||
|
||||
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||
|
||||
|
||||
$cache = $this->getMock('Doctrine\Common\Cache\AbstractCache', array('_doFetch', '_doContains', '_doSave', '_doDelete', 'getIds'));
|
||||
$cache->expects($this->at(0))
|
||||
->method('_doFetch')
|
||||
|
||||
@@ -34,9 +34,9 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->clear();
|
||||
|
||||
$query = $this->_em->createQuery("select u, upper(u.name) from Doctrine\Tests\Models\CMS\CmsUser u where u.username = 'gblanco'");
|
||||
|
||||
|
||||
$result = $query->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(1, count($result));
|
||||
$this->assertTrue($result[0][0] instanceof CmsUser);
|
||||
$this->assertEquals('Guilherme', $result[0][0]->name);
|
||||
@@ -109,7 +109,7 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$q = $this->_em->createQuery('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = ?0');
|
||||
$q->setParameter(0, 'jwage');
|
||||
$user = $q->getSingleResult();
|
||||
|
||||
|
||||
$this->assertNotNull($user);
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$identityMap = $this->_em->getUnitOfWork()->getIdentityMap();
|
||||
$identityMapCount = count($identityMap['Doctrine\Tests\Models\CMS\CmsArticle']);
|
||||
$this->assertTrue($identityMapCount>$iteratedCount);
|
||||
|
||||
|
||||
$iteratedCount++;
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$query = $this->_em->createQuery("SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.articles a");
|
||||
$articles = $query->iterate();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @expectedException Doctrine\ORM\NoResultException
|
||||
*/
|
||||
@@ -366,7 +366,7 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertTrue($result[0]->user instanceof \Doctrine\ORM\Proxy\Proxy);
|
||||
$this->assertFalse($result[0]->user->__isInitialized__);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-952
|
||||
*/
|
||||
@@ -386,11 +386,11 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
}
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$articles = $this->_em->createQuery('select a from Doctrine\Tests\Models\CMS\CmsArticle a')
|
||||
->setFetchMode('Doctrine\Tests\Models\CMS\CmsArticle', 'user', ClassMetadata::FETCH_EAGER)
|
||||
->getResult();
|
||||
|
||||
|
||||
$this->assertEquals(10, count($articles));
|
||||
foreach ($articles AS $article) {
|
||||
$this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $article);
|
||||
@@ -456,7 +456,43 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$query = $this->_em->createQuery("select u.username from Doctrine\Tests\Models\CMS\CmsUser u where u.username = 'gblanco'");
|
||||
$this->assertNull($query->getOneOrNullResult(Query::HYDRATE_SCALAR));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group DBAL-171
|
||||
*/
|
||||
public function testParameterOrder()
|
||||
{
|
||||
$user1 = new CmsUser;
|
||||
$user1->name = 'Benjamin';
|
||||
$user1->username = 'beberlei';
|
||||
$user1->status = 'developer';
|
||||
$this->_em->persist($user1);
|
||||
|
||||
$user2 = new CmsUser;
|
||||
$user2->name = 'Roman';
|
||||
$user2->username = 'romanb';
|
||||
$user2->status = 'developer';
|
||||
$this->_em->persist($user2);
|
||||
|
||||
$user3 = new CmsUser;
|
||||
$user3->name = 'Jonathan';
|
||||
$user3->username = 'jwage';
|
||||
$user3->status = 'developer';
|
||||
$this->_em->persist($user3);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$query = $this->_em->createQuery("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.status = :a AND u.id IN (:b)");
|
||||
$query->setParameters(array(
|
||||
'b' => array($user1->id, $user2->id, $user3->id),
|
||||
'a' => 'developer',
|
||||
));
|
||||
$result = $query->getResult();
|
||||
|
||||
$this->assertEquals(3, count($result));
|
||||
}
|
||||
|
||||
public function testDqlWithAutoInferOfParameters()
|
||||
{
|
||||
$user = new CmsUser;
|
||||
@@ -464,30 +500,30 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$user->username = 'beberlei';
|
||||
$user->status = 'developer';
|
||||
$this->_em->persist($user);
|
||||
|
||||
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Roman';
|
||||
$user->username = 'romanb';
|
||||
$user->status = 'developer';
|
||||
$this->_em->persist($user);
|
||||
|
||||
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Jonathan';
|
||||
$user->username = 'jwage';
|
||||
$user->status = 'developer';
|
||||
$this->_em->persist($user);
|
||||
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$query = $this->_em->createQuery("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username IN (?0)");
|
||||
$query->setParameter(0, array('beberlei', 'jwage'));
|
||||
|
||||
|
||||
$users = $query->execute();
|
||||
|
||||
|
||||
$this->assertEquals(2, count($users));
|
||||
}
|
||||
|
||||
|
||||
public function testQueryBuilderWithStringWhereClauseContainingOrAndConditionalPrimary()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder();
|
||||
@@ -495,13 +531,13 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
|
||||
->innerJoin('u.articles', 'a')
|
||||
->where('(u.id = 0) OR (u.id IS NULL)');
|
||||
|
||||
|
||||
$query = $qb->getQuery();
|
||||
$users = $query->execute();
|
||||
|
||||
|
||||
$this->assertEquals(0, count($users));
|
||||
}
|
||||
|
||||
|
||||
public function testQueryWithArrayOfEntitiesAsParameter()
|
||||
{
|
||||
$userA = new CmsUser;
|
||||
@@ -509,28 +545,28 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$userA->username = 'beberlei';
|
||||
$userA->status = 'developer';
|
||||
$this->_em->persist($userA);
|
||||
|
||||
|
||||
$userB = new CmsUser;
|
||||
$userB->name = 'Roman';
|
||||
$userB->username = 'romanb';
|
||||
$userB->status = 'developer';
|
||||
$this->_em->persist($userB);
|
||||
|
||||
|
||||
$userC = new CmsUser;
|
||||
$userC->name = 'Jonathan';
|
||||
$userC->username = 'jwage';
|
||||
$userC->status = 'developer';
|
||||
$this->_em->persist($userC);
|
||||
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$query = $this->_em->createQuery("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u IN (?0) OR u.username = ?1");
|
||||
$query->setParameter(0, array($userA, $userC));
|
||||
$query->setParameter(1, 'beberlei');
|
||||
|
||||
|
||||
$users = $query->execute();
|
||||
|
||||
|
||||
$this->assertEquals(2, count($users));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@ require_once __DIR__ . '/../../TestInit.php';
|
||||
class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp() {
|
||||
if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
|
||||
$this->markTestSkipped('Test not compatible with 2.2 common');
|
||||
}
|
||||
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
}
|
||||
@@ -33,7 +37,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||
|
||||
$cache = new ArrayCache();
|
||||
|
||||
|
||||
$query->setResultCacheDriver($cache)->setResultCacheId('my_cache_id');
|
||||
|
||||
$this->assertFalse($cache->contains('my_cache_id'));
|
||||
@@ -65,7 +69,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$query->setResultCacheId('testing_result_cache_id');
|
||||
|
||||
$this->assertFalse($cache->contains('testing_result_cache_id'));
|
||||
|
||||
|
||||
$users = $query->getResult();
|
||||
|
||||
$this->assertTrue($cache->contains('testing_result_cache_id'));
|
||||
@@ -124,7 +128,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$cache = new ArrayCache();
|
||||
$query->setResultCacheDriver($cache)->useResultCache(true);
|
||||
|
||||
|
||||
$this->assertEquals(0, count($cache->getIds()));
|
||||
$query->getResult();
|
||||
$this->assertEquals(1, count($cache->getIds()));
|
||||
@@ -218,7 +222,7 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$query2 = $this->_em->createQuery('select a from Doctrine\Tests\Models\CMS\CmsArticle a WHERE a.user = ?1');
|
||||
$query2->setParameter(1, $user1);
|
||||
|
||||
|
||||
$query2->setResultCacheDriver($cache)->useResultCache(true);
|
||||
|
||||
$articles = $query2->getResult();
|
||||
|
||||
@@ -21,7 +21,7 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$address = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress');
|
||||
$this->assertEquals(1, $address->sequenceGeneratorDefinition['allocationSize']);
|
||||
}
|
||||
|
||||
|
||||
public function testGetCreateSchemaSql()
|
||||
{
|
||||
$classes = array(
|
||||
@@ -32,7 +32,7 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$tool = new SchemaTool($this->_em);
|
||||
$sql = $tool->getCreateSchemaSql($classes);
|
||||
|
||||
|
||||
$this->assertEquals("CREATE TABLE cms_addresses (id INT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, PRIMARY KEY(id))", $sql[0]);
|
||||
$this->assertEquals("CREATE UNIQUE INDEX UNIQ_ACAC157BA76ED395 ON cms_addresses (user_id)", $sql[1]);
|
||||
$this->assertEquals("CREATE TABLE cms_users (id INT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))", $sql[2]);
|
||||
@@ -48,10 +48,10 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals("ALTER TABLE cms_users_groups ADD CONSTRAINT FK_7EA9409AA76ED395 FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[12]);
|
||||
$this->assertEquals("ALTER TABLE cms_users_groups ADD CONSTRAINT FK_7EA9409AFE54D947 FOREIGN KEY (group_id) REFERENCES cms_groups(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[13]);
|
||||
$this->assertEquals("ALTER TABLE cms_phonenumbers ADD CONSTRAINT FK_F21F790FA76ED395 FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[14]);
|
||||
|
||||
|
||||
$this->assertEquals(count($sql), 15);
|
||||
}
|
||||
|
||||
|
||||
public function testGetCreateSchemaSql2()
|
||||
{
|
||||
$classes = array(
|
||||
@@ -62,11 +62,11 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$sql = $tool->getCreateSchemaSql($classes);
|
||||
|
||||
$this->assertEquals(2, count($sql));
|
||||
|
||||
|
||||
$this->assertEquals('CREATE TABLE decimal_model (id INT NOT NULL, "decimal" NUMERIC(5, 2) NOT NULL, "high_scale" NUMERIC(14, 4) NOT NULL, PRIMARY KEY(id))', $sql[0]);
|
||||
$this->assertEquals("CREATE SEQUENCE decimal_model_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[1]);
|
||||
}
|
||||
|
||||
|
||||
public function testGetCreateSchemaSql3()
|
||||
{
|
||||
$classes = array(
|
||||
@@ -75,12 +75,12 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$tool = new SchemaTool($this->_em);
|
||||
$sql = $tool->getCreateSchemaSql($classes);
|
||||
|
||||
|
||||
$this->assertEquals(2, count($sql));
|
||||
$this->assertEquals("CREATE TABLE boolean_model (id INT NOT NULL, booleanField BOOLEAN NOT NULL, PRIMARY KEY(id))", $sql[0]);
|
||||
$this->assertEquals("CREATE SEQUENCE boolean_model_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[1]);
|
||||
}
|
||||
|
||||
|
||||
public function testGetDropSchemaSql()
|
||||
{
|
||||
$classes = array(
|
||||
@@ -96,8 +96,8 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
}
|
||||
$sql = $tool->getDropSchemaSQL($classes);
|
||||
|
||||
$this->assertEquals(10, count($sql));
|
||||
|
||||
$this->assertEquals(13, count($sql));
|
||||
$dropSequenceSQLs = 0;
|
||||
foreach ($sql AS $stmt) {
|
||||
if (strpos($stmt, "DROP SEQUENCE") === 0) {
|
||||
|
||||
@@ -8,18 +8,18 @@ require_once __DIR__ . '/../../../TestInit.php';
|
||||
* @group DDC-1151
|
||||
*/
|
||||
class DDC1151Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
{
|
||||
public function testQuoteForeignKey()
|
||||
{
|
||||
if ($this->_em->getConnection()->getDatabasePlatform()->getName() != 'postgresql') {
|
||||
$this->markTestSkipped("This test is useful for all databases, but designed only for postgresql.");
|
||||
}
|
||||
|
||||
|
||||
$sql = $this->_schemaTool->getCreateSchemaSql(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1151User'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1151Group'),
|
||||
));
|
||||
|
||||
|
||||
$this->assertEquals("CREATE TABLE \"User\" (id INT NOT NULL, PRIMARY KEY(id))", $sql[0]);
|
||||
$this->assertEquals("CREATE TABLE ddc1151user_ddc1151group (ddc1151user_id INT NOT NULL, ddc1151group_id INT NOT NULL, PRIMARY KEY(ddc1151user_id, ddc1151group_id))", $sql[1]);
|
||||
$this->assertEquals("CREATE INDEX IDX_88A3259AC5AD08A ON ddc1151user_ddc1151group (ddc1151user_id)", $sql[2]);
|
||||
@@ -27,8 +27,8 @@ class DDC1151Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals("CREATE TABLE \"Group\" (id INT NOT NULL, PRIMARY KEY(id))", $sql[4]);
|
||||
$this->assertEquals("CREATE SEQUENCE User_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[5]);
|
||||
$this->assertEquals("CREATE SEQUENCE Group_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[6]);
|
||||
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD FOREIGN KEY (ddc1151user_id) REFERENCES \"User\"(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[7]);
|
||||
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD FOREIGN KEY (ddc1151group_id) REFERENCES \"Group\"(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[8]);
|
||||
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD CONSTRAINT FK_88A3259AC5AD08A FOREIGN KEY (ddc1151user_id) REFERENCES \"User\"(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[7]);
|
||||
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD CONSTRAINT FK_88A32597357E0B1 FOREIGN KEY (ddc1151group_id) REFERENCES \"Group\"(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[8]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class DDC1151User
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
|
||||
|
||||
/** @ManyToMany(targetEntity="DDC1151Group") */
|
||||
public $groups;
|
||||
}
|
||||
|
||||
@@ -209,8 +209,15 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->article1->addTranslation('en', 'Bar');
|
||||
$this->article1->addTranslation('en', 'Baz');
|
||||
|
||||
$this->setExpectedException('Exception');
|
||||
$this->_em->flush();
|
||||
$exceptionThrown = false;
|
||||
try {
|
||||
// exception depending on the underyling Database Driver
|
||||
$this->_em->flush();
|
||||
} catch(\Exception $e) {
|
||||
$exceptionThrown = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($exceptionThrown, "The underlying database driver throws an exception.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -410,4 +417,20 @@ class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
return $this->_em->find(get_class($editor), $editor->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1519
|
||||
*/
|
||||
public function testMergeForeignKeyIdentifierEntity()
|
||||
{
|
||||
$idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
|
||||
|
||||
$refRep = $this->_em->find("Doctrine\Tests\Models\DDC117\DDC117Reference", $idCriteria);
|
||||
|
||||
$this->_em->detach($refRep);
|
||||
$refRep = $this->_em->merge($refRep);
|
||||
|
||||
$this->assertEquals($this->article1->id(), $refRep->source()->id());
|
||||
$this->assertEquals($this->article2->id(), $refRep->target()->id());
|
||||
}
|
||||
}
|
||||
|
||||
99
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1383Test.php
Normal file
99
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1383Test.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1383
|
||||
*/
|
||||
class DDC1383Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1383AbstractEntity'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1383Entity'),
|
||||
));
|
||||
} catch(\Exception $ignored) {}
|
||||
}
|
||||
|
||||
public function testFailingCase()
|
||||
{
|
||||
$parent = new DDC1383Entity();
|
||||
$child = new DDC1383Entity();
|
||||
|
||||
$child->setReference($parent);
|
||||
|
||||
$this->_em->persist($parent);
|
||||
$this->_em->persist($child);
|
||||
|
||||
$id = $child->getId();
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
// Try merging the parent entity
|
||||
$child = $this->_em->merge($child);
|
||||
$parent = $child->getReference();
|
||||
|
||||
// Parent is not instance of the abstract class
|
||||
self::assertTrue($parent instanceof DDC1383AbstractEntity,
|
||||
"Entity class is " . get_class($parent) . ', "DDC1383AbstractEntity" was expected');
|
||||
|
||||
// Parent is NOT instance of entity
|
||||
self::assertTrue($parent instanceof DDC1383Entity,
|
||||
"Entity class is " . get_class($parent) . ', "DDC1383Entity" was expected');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @InheritanceType("JOINED")
|
||||
* @DiscriminatorColumn(name="discr", type="integer")
|
||||
* @DiscriminatorMap({1 = "DDC1383Entity"})
|
||||
*/
|
||||
abstract class DDC1383AbstractEntity
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1383Entity extends DDC1383AbstractEntity
|
||||
{
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC1383AbstractEntity")
|
||||
*/
|
||||
protected $reference;
|
||||
|
||||
public function getReference()
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
|
||||
public function setReference(DDC1383AbstractEntity $reference)
|
||||
{
|
||||
$this->reference = $reference;
|
||||
}
|
||||
}
|
||||
127
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1452Test.php
Normal file
127
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1452Test.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1452
|
||||
*/
|
||||
class DDC1452Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1452EntityA'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1452EntityB'),
|
||||
));
|
||||
} catch (\Exception $ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$a1 = new DDC1452EntityA();
|
||||
$a1->title = "foo";
|
||||
|
||||
$a2 = new DDC1452EntityA();
|
||||
$a2->title = "bar";
|
||||
|
||||
$b = new DDC1452EntityB();
|
||||
$b->entityAFrom = $a1;
|
||||
$b->entityATo = $a2;
|
||||
|
||||
$this->_em->persist($a1);
|
||||
$this->_em->persist($a2);
|
||||
$this->_em->persist($b);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$dql = "SELECT a, b, ba FROM " . __NAMESPACE__ . "\DDC1452EntityA AS a LEFT JOIN a.entitiesB AS b LEFT JOIN b.entityATo AS ba";
|
||||
$results = $this->_em->createQuery($dql)->setMaxResults(1)->getResult();
|
||||
|
||||
$this->assertSame($results[0], $results[0]->entitiesB[0]->entityAFrom);
|
||||
$this->assertFalse( $results[0]->entitiesB[0]->entityATo instanceof \Doctrine\ORM\Proxy\Proxy );
|
||||
$this->assertInstanceOf('Doctrine\Common\Collections\Collection', $results[0]->entitiesB[0]->entityATo->getEntitiesB());
|
||||
}
|
||||
|
||||
public function testFetchJoinOneToOneFromInverse()
|
||||
{
|
||||
$address = new \Doctrine\Tests\Models\CMS\CmsAddress();
|
||||
$address->city = "Bonn";
|
||||
$address->country = "Germany";
|
||||
$address->street = "Somestreet";
|
||||
$address->zip = 12345;
|
||||
|
||||
$user = new \Doctrine\Tests\Models\CMS\CmsUser();
|
||||
$user->name = "beberlei";
|
||||
$user->username = "beberlei";
|
||||
$user->status = "active";
|
||||
$user->address = $address;
|
||||
$address->user = $user;
|
||||
|
||||
$this->_em->persist($address);
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$dql = "SELECT a, u FROM Doctrine\Tests\Models\CMS\CmsAddress a INNER JOIN a.user u";
|
||||
$data = $this->_em->createQuery($dql)->getResult();
|
||||
$this->_em->clear();
|
||||
|
||||
$this->assertFalse($data[0]->user instanceof \Doctrine\ORM\Proxy\Proxy);
|
||||
|
||||
$dql = "SELECT u, a FROM Doctrine\Tests\Models\CMS\CmsUser u INNER JOIN u.address a";
|
||||
$data = $this->_em->createQuery($dql)->getResult();
|
||||
|
||||
$this->assertFalse($data[0]->address instanceof \Doctrine\ORM\Proxy\Proxy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1452EntityA
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
/** @Column */
|
||||
public $title;
|
||||
/** @ManyToMany(targetEntity="DDC1452EntityB", mappedBy="entityAFrom") */
|
||||
public $entitiesB;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->entitiesB = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getEntitiesB()
|
||||
{
|
||||
return $this->entitiesB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1452EntityB
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC1452EntityA", inversedBy="entitiesB")
|
||||
*/
|
||||
public $entityAFrom;
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC1452EntityA")
|
||||
*/
|
||||
public $entityATo;
|
||||
}
|
||||
69
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1454Test.php
Normal file
69
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1454Test.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1454
|
||||
*/
|
||||
class DDC1454Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1454File'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1454Picture'),
|
||||
));
|
||||
} catch (\Exception $ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function testFailingCase()
|
||||
{
|
||||
$pic = new DDC1454Picture();
|
||||
$this->_em->getUnitOfWork()->getEntityState($pic);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1454Picture extends DDC1454File
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @InheritanceType("JOINED")
|
||||
* @DiscriminatorColumn(name="discr", type="string")
|
||||
* @DiscriminatorMap({"picture" = "DDC1454Picture"})
|
||||
*/
|
||||
class DDC1454File
|
||||
{
|
||||
/**
|
||||
* @Column(name="file_id", type="integer")
|
||||
* @Id
|
||||
*/
|
||||
public $fileId;
|
||||
|
||||
public function __construct() {
|
||||
$this->fileId = rand();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fileId
|
||||
*/
|
||||
public function getFileId() {
|
||||
return $this->fileId;
|
||||
}
|
||||
|
||||
}
|
||||
131
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1458Test.php
Normal file
131
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1458Test.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
use Doctrine\Tests\Models\CMS\CmsGroup;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
class DDC1258Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\TestEntity'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\TestAdditionalEntity')
|
||||
));
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$testEntity = new TestEntity();
|
||||
$testEntity->setValue(3);
|
||||
$testEntity->setAdditional(new TestAdditionalEntity());
|
||||
$this->_em->persist($testEntity);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
// So here the value is 3
|
||||
$this->assertEquals(3, $testEntity->getValue());
|
||||
|
||||
$test = $this->_em->getRepository(__NAMESPACE__ . '\TestEntity')->find(1);
|
||||
|
||||
// New value is set
|
||||
$test->setValue(5);
|
||||
|
||||
// So here the value is 5
|
||||
$this->assertEquals(5, $test->getValue());
|
||||
|
||||
// Get the additional entity
|
||||
$additional = $test->getAdditional();
|
||||
|
||||
// Still 5..
|
||||
$this->assertEquals(5, $test->getValue());
|
||||
|
||||
// Force the proxy to load
|
||||
$additional->getBool();
|
||||
|
||||
// The value should still be 5
|
||||
$this->assertEquals(5, $test->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class TestEntity
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $id;
|
||||
/**
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
protected $value;
|
||||
/**
|
||||
* @OneToOne(targetEntity="TestAdditionalEntity", inversedBy="entity", orphanRemoval=true, cascade={"persist", "remove"})
|
||||
*/
|
||||
protected $additional;
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getAdditional()
|
||||
{
|
||||
return $this->additional;
|
||||
}
|
||||
|
||||
public function setAdditional($additional)
|
||||
{
|
||||
$this->additional = $additional;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class TestAdditionalEntity
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $id;
|
||||
/**
|
||||
* @OneToOne(targetEntity="TestEntity", mappedBy="additional")
|
||||
*/
|
||||
protected $entity;
|
||||
/**
|
||||
* @Column(type="boolean")
|
||||
*/
|
||||
protected $bool;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->bool = false;
|
||||
}
|
||||
|
||||
public function getBool()
|
||||
{
|
||||
return $this->bool;
|
||||
}
|
||||
|
||||
public function setBool($bool)
|
||||
{
|
||||
$this->bool = $bool;
|
||||
}
|
||||
}
|
||||
146
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1509Test.php
Normal file
146
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1509Test.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
/**
|
||||
* @group DDC-1509
|
||||
*/
|
||||
class DDC1509Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1509AbstractFile'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1509File'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1509Picture'),
|
||||
));
|
||||
} catch (\Exception $ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function testFailingCase()
|
||||
{
|
||||
$file = new DDC1509File;
|
||||
$thumbnail = new DDC1509File;
|
||||
|
||||
$picture = new DDC1509Picture;
|
||||
$picture->setFile($file);
|
||||
$picture->setThumbnail($thumbnail);
|
||||
|
||||
|
||||
/* @var $em \Doctrine\ORM\EntityManager */
|
||||
$em = $this->_em;
|
||||
$em->persist($picture);
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$id = $picture->getPictureId();
|
||||
|
||||
$pic = $em->merge($picture);
|
||||
/* @var $pic DDC1509Picture */
|
||||
|
||||
$this->assertNotNull($pic->getThumbnail());
|
||||
$this->assertNotNull($pic->getFile());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1509Picture
|
||||
{
|
||||
|
||||
/**
|
||||
* @Column(type="integer")
|
||||
* @Id
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC1509AbstractFile", cascade={"persist", "remove"})
|
||||
*/
|
||||
private $thumbnail;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC1509AbstractFile", cascade={"persist", "remove"})
|
||||
*/
|
||||
private $file;
|
||||
|
||||
/**
|
||||
* Get pictureId
|
||||
*/
|
||||
public function getPictureId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file
|
||||
*/
|
||||
public function setFile($value = null)
|
||||
{
|
||||
$this->file = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file
|
||||
*/
|
||||
public function getFile()
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function getThumbnail()
|
||||
{
|
||||
return $this->thumbnail;
|
||||
}
|
||||
|
||||
public function setThumbnail($thumbnail)
|
||||
{
|
||||
$this->thumbnail = $thumbnail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @InheritanceType("SINGLE_TABLE")
|
||||
* @DiscriminatorColumn(name="discr", type="string")
|
||||
* @DiscriminatorMap({"file" = "DDC1509File"})
|
||||
*/
|
||||
class DDC1509AbstractFile
|
||||
{
|
||||
|
||||
/**
|
||||
* @Column(type="integer")
|
||||
* @Id
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* Get fileId
|
||||
*/
|
||||
public function getFileId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1509File extends DDC1509AbstractFile
|
||||
{
|
||||
|
||||
}
|
||||
111
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1514Test.php
Normal file
111
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1514Test.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1514
|
||||
*/
|
||||
class DDC1514Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
try {
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1514EntityA'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1514EntityB'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1514EntityC'),
|
||||
));
|
||||
} catch (\Exception $ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$a1 = new DDC1514EntityA();
|
||||
$a1->title = "foo";
|
||||
|
||||
$a2 = new DDC1514EntityA();
|
||||
$a2->title = "bar";
|
||||
|
||||
$b1 = new DDC1514EntityB();
|
||||
$b1->entityAFrom = $a1;
|
||||
$b1->entityATo = $a2;
|
||||
|
||||
$b2 = new DDC1514EntityB();
|
||||
$b2->entityAFrom = $a2;
|
||||
$b2->entityATo = $a1;
|
||||
|
||||
$c = new DDC1514EntityC();
|
||||
$c->title = "baz";
|
||||
$a2->entityC = $c;
|
||||
|
||||
$this->_em->persist($a1);
|
||||
$this->_em->persist($a2);
|
||||
$this->_em->persist($b1);
|
||||
$this->_em->persist($b2);
|
||||
$this->_em->persist($c);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$dql = "SELECT a, b, ba, c FROM " . __NAMESPACE__ . "\DDC1514EntityA AS a LEFT JOIN a.entitiesB AS b LEFT JOIN b.entityATo AS ba LEFT JOIN a.entityC AS c";
|
||||
$results = $this->_em->createQuery($dql)->getResult();
|
||||
|
||||
$this->assertEquals($c->title, $results[1]->entityC->title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1514EntityA
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
/** @Column */
|
||||
public $title;
|
||||
/** @ManyToMany(targetEntity="DDC1514EntityB", mappedBy="entityAFrom") */
|
||||
public $entitiesB;
|
||||
/** @ManyToOne(targetEntity="DDC1514EntityC") */
|
||||
public $entityC;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->entitiesB = new ArrayCollection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1514EntityB
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC1514EntityA", inversedBy="entitiesB")
|
||||
*/
|
||||
public $entityAFrom;
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC1514EntityA")
|
||||
*/
|
||||
public $entityATo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1514EntityC
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
public $id;
|
||||
/** @Column */
|
||||
public $title;
|
||||
}
|
||||
64
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1515Test.php
Normal file
64
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1515Test.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
|
||||
/**
|
||||
* @group DDC-1515
|
||||
*/
|
||||
class DDC1515Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1515Foo'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1515Bar'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$bar = new DDC1515Bar();
|
||||
$this->_em->persist($bar);
|
||||
$this->_em->flush();
|
||||
|
||||
$foo = new DDC1515Foo();
|
||||
$foo->bar = $bar;
|
||||
$this->_em->persist($foo);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$bar = $this->_em->find(__NAMESPACE__ . '\DDC1515Bar', $bar->id);
|
||||
$this->assertInstanceOf(__NAMESPACE__.'\DDC1515Foo', $bar->foo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1515Foo
|
||||
{
|
||||
/**
|
||||
* @OneToOne(targetEntity="DDC1515Bar", inversedBy="foo") @Id
|
||||
*/
|
||||
public $bar;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1515Bar
|
||||
{
|
||||
/**
|
||||
* @Id @Column(type="integer") @GeneratedValue
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @OneToOne(targetEntity="DDC1515Foo", mappedBy="bar")
|
||||
*/
|
||||
public $foo;
|
||||
}
|
||||
|
||||
|
||||
67
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1526Test.php
Normal file
67
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1526Test.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
/**
|
||||
* @group DDC-1526
|
||||
*/
|
||||
class DDC1526Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1526Menu'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$parents = array();
|
||||
for ($i = 0; $i < 9; $i++) {
|
||||
$entity = new DDC1526Menu;
|
||||
|
||||
if (isset ($parents[($i % 3)])) {
|
||||
$entity->parent = $parents[($i%3)];
|
||||
}
|
||||
|
||||
$this->_em->persist($entity);
|
||||
$parents[$i] = $entity;
|
||||
}
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
|
||||
$dql = "SELECT m, c
|
||||
FROM " . __NAMESPACE__ . "\DDC1526Menu m
|
||||
LEFT JOIN m.children c";
|
||||
$menus = $this->_em->createQuery($dql)->getResult();
|
||||
|
||||
// All Children collection now have to be initiailzed
|
||||
foreach ($menus as $menu) {
|
||||
$this->assertTrue($menu->children->isInitialized());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1526Menu
|
||||
{
|
||||
/**
|
||||
* @Column(type="integer")
|
||||
* @Id
|
||||
* @GeneratedValue
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @ManyToOne(targetEntity="DDC1526Menu", inversedBy="children")
|
||||
*/
|
||||
public $parent;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="DDC1526Menu", mappedBy="parent")
|
||||
*/
|
||||
public $children;
|
||||
}
|
||||
203
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1545Test.php
Normal file
203
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1545Test.php
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Tests\Models\Qelista\User;
|
||||
|
||||
use Doctrine\Tests\Models\Qelista\ShoppingList;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Tests\Models\CMS\CmsComment;
|
||||
use Doctrine\Tests\Models\CMS\CmsArticle;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1545
|
||||
*/
|
||||
class DDC1545Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
private $articleId;
|
||||
|
||||
private $userId;
|
||||
|
||||
private $user2Id;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
private function initDb($link)
|
||||
{
|
||||
$article = new CmsArticle();
|
||||
$article->topic = 'foo';
|
||||
$article->text = 'foo';
|
||||
|
||||
$user = new CmsUser();
|
||||
$user->status = 'foo';
|
||||
$user->username = 'foo';
|
||||
$user->name = 'foo';
|
||||
|
||||
$user2 = new CmsUser();
|
||||
$user2->status = 'bar';
|
||||
$user2->username = 'bar';
|
||||
$user2->name = 'bar';
|
||||
|
||||
if ($link) {
|
||||
$article->user = $user;
|
||||
}
|
||||
|
||||
$this->_em->persist($article);
|
||||
$this->_em->persist($user);
|
||||
$this->_em->persist($user2);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$this->articleId = $article->id;
|
||||
$this->userId = $user->id;
|
||||
$this->user2Id = $user2->id;
|
||||
}
|
||||
|
||||
public function testLinkObjects()
|
||||
{
|
||||
$this->initDb(false);
|
||||
|
||||
// don't join association
|
||||
$article = $this->_em->find('Doctrine\Tests\Models\Cms\CmsArticle', $this->articleId);
|
||||
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\Cms\CmsUser', $this->userId);
|
||||
|
||||
$article->user = $user;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$article = $this->_em
|
||||
->createQuery('SELECT a, u FROM Doctrine\Tests\Models\Cms\CmsArticle a LEFT JOIN a.user u WHERE a.id = :id')
|
||||
->setParameter('id', $this->articleId)
|
||||
->getOneOrNullResult();
|
||||
|
||||
$this->assertNotNull($article->user);
|
||||
$this->assertEquals($user->id, $article->user->id);
|
||||
}
|
||||
|
||||
public function testLinkObjectsWithAssociationLoaded()
|
||||
{
|
||||
$this->initDb(false);
|
||||
|
||||
// join association
|
||||
$article = $this->_em
|
||||
->createQuery('SELECT a, u FROM Doctrine\Tests\Models\Cms\CmsArticle a LEFT JOIN a.user u WHERE a.id = :id')
|
||||
->setParameter('id', $this->articleId)
|
||||
->getOneOrNullResult();
|
||||
|
||||
$user = $this->_em->find('Doctrine\Tests\Models\Cms\CmsUser', $this->userId);
|
||||
|
||||
$article->user = $user;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$article = $this->_em
|
||||
->createQuery('SELECT a, u FROM Doctrine\Tests\Models\Cms\CmsArticle a LEFT JOIN a.user u WHERE a.id = :id')
|
||||
->setParameter('id', $this->articleId)
|
||||
->getOneOrNullResult();
|
||||
|
||||
$this->assertNotNull($article->user);
|
||||
$this->assertEquals($user->id, $article->user->id);
|
||||
}
|
||||
|
||||
public function testUnlinkObjects()
|
||||
{
|
||||
$this->initDb(true);
|
||||
|
||||
// don't join association
|
||||
$article = $this->_em->find('Doctrine\Tests\Models\Cms\CmsArticle', $this->articleId);
|
||||
|
||||
$article->user = null;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$article = $this->_em
|
||||
->createQuery('SELECT a, u FROM Doctrine\Tests\Models\Cms\CmsArticle a LEFT JOIN a.user u WHERE a.id = :id')
|
||||
->setParameter('id', $this->articleId)
|
||||
->getOneOrNullResult();
|
||||
|
||||
$this->assertNull($article->user);
|
||||
}
|
||||
|
||||
public function testUnlinkObjectsWithAssociationLoaded()
|
||||
{
|
||||
$this->initDb(true);
|
||||
|
||||
// join association
|
||||
$article = $this->_em
|
||||
->createQuery('SELECT a, u FROM Doctrine\Tests\Models\Cms\CmsArticle a LEFT JOIN a.user u WHERE a.id = :id')
|
||||
->setParameter('id', $this->articleId)
|
||||
->getOneOrNullResult();
|
||||
|
||||
$article->user = null;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$article = $this->_em
|
||||
->createQuery('SELECT a, u FROM Doctrine\Tests\Models\Cms\CmsArticle a LEFT JOIN a.user u WHERE a.id = :id')
|
||||
->setParameter('id', $this->articleId)
|
||||
->getOneOrNullResult();
|
||||
|
||||
$this->assertNull($article->user);
|
||||
}
|
||||
|
||||
public function testChangeLink()
|
||||
{
|
||||
$this->initDb(false);
|
||||
|
||||
// don't join association
|
||||
$article = $this->_em->find('Doctrine\Tests\Models\Cms\CmsArticle', $this->articleId);
|
||||
|
||||
$user2 = $this->_em->find('Doctrine\Tests\Models\Cms\CmsUser', $this->user2Id);
|
||||
|
||||
$article->user = $user2;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$article = $this->_em
|
||||
->createQuery('SELECT a, u FROM Doctrine\Tests\Models\Cms\CmsArticle a LEFT JOIN a.user u WHERE a.id = :id')
|
||||
->setParameter('id', $this->articleId)
|
||||
->getOneOrNullResult();
|
||||
|
||||
$this->assertNotNull($article->user);
|
||||
$this->assertEquals($user2->id, $article->user->id);
|
||||
}
|
||||
|
||||
public function testChangeLinkWithAssociationLoaded()
|
||||
{
|
||||
$this->initDb(false);
|
||||
|
||||
// join association
|
||||
$article = $this->_em
|
||||
->createQuery('SELECT a, u FROM Doctrine\Tests\Models\Cms\CmsArticle a LEFT JOIN a.user u WHERE a.id = :id')
|
||||
->setParameter('id', $this->articleId)
|
||||
->getOneOrNullResult();
|
||||
|
||||
$user2 = $this->_em->find('Doctrine\Tests\Models\Cms\CmsUser', $this->user2Id);
|
||||
|
||||
$article->user = $user2;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$article = $this->_em
|
||||
->createQuery('SELECT a, u FROM Doctrine\Tests\Models\Cms\CmsArticle a LEFT JOIN a.user u WHERE a.id = :id')
|
||||
->setParameter('id', $this->articleId)
|
||||
->getOneOrNullResult();
|
||||
|
||||
$this->assertNotNull($article->user);
|
||||
$this->assertEquals($user2->id, $article->user->id);
|
||||
}
|
||||
}
|
||||
80
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1548Test.php
Normal file
80
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1548Test.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
/**
|
||||
* @group DDC-1548
|
||||
*/
|
||||
class DDC1548Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1548E1'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1548E2'),
|
||||
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1548Rel'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$rel = new DDC1548Rel();
|
||||
$this->_em->persist($rel);
|
||||
$this->_em->flush();
|
||||
|
||||
$e1 = new DDC1548E1();
|
||||
$e1->rel = $rel;
|
||||
$this->_em->persist($e1);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$obt = $this->_em->find(__NAMESPACE__ . '\DDC1548Rel', $rel->id);
|
||||
|
||||
$this->assertNull($obt->e2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1548E1
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @OneToOne(targetEntity="DDC1548Rel", inversedBy="e1")
|
||||
*/
|
||||
public $rel;
|
||||
}
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1548E2
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @OneToOne(targetEntity="DDC1548Rel", inversedBy="e2")
|
||||
*/
|
||||
public $rel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1548Rel
|
||||
{
|
||||
/**
|
||||
* @Id @GeneratedValue
|
||||
* @Column(type="integer")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @OneToOne(targetEntity="DDC1548E1", mappedBy="rel")
|
||||
*/
|
||||
public $e1;
|
||||
/**
|
||||
* @OneToOne(targetEntity="DDC1548E2", mappedBy="rel")
|
||||
*/
|
||||
public $e2;
|
||||
}
|
||||
45
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1594Test.php
Normal file
45
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1594Test.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
use Doctrine\Tests\Models\CMS\CmsComment;
|
||||
use Doctrine\Tests\Models\CMS\CmsArticle;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
|
||||
/**
|
||||
* @group DDC-1594
|
||||
*/
|
||||
class DDC1594Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testIssue()
|
||||
{
|
||||
$user = new CmsUser();
|
||||
$user->status = 'foo';
|
||||
$user->username = 'foo';
|
||||
$user->name = 'foo';
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->clear();
|
||||
$detachedUser = clone $user;
|
||||
$detachedUser->name = 'bar';
|
||||
$detachedUser->status = 'bar';
|
||||
|
||||
$newUser = $this->_em->getReference(get_class($user), $user->id);
|
||||
|
||||
$mergedUser = $this->_em->merge($detachedUser);
|
||||
|
||||
$this->assertNotSame($mergedUser, $detachedUser);
|
||||
$this->assertEquals('bar', $detachedUser->getName());
|
||||
$this->assertEquals('bar', $mergedUser->getName());
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ class DDC258Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$e2 = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC258Super', $c2->id);
|
||||
|
||||
$this->assertType('Doctrine\Tests\ORM\Functional\Ticket\DDC258Class2', $e2);
|
||||
$this->assertInstanceOf('Doctrine\Tests\ORM\Functional\Ticket\DDC258Class2', $e2);
|
||||
$this->assertEquals('Bar', $e2->title);
|
||||
$this->assertEquals('Bar', $e2->description);
|
||||
$this->assertEquals('Bar', $e2->text);
|
||||
|
||||
@@ -64,13 +64,13 @@ class DDC440Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
// Test the first phone. The assertion actually failed because original entity data is not set properly.
|
||||
// This was because it is also set as MainPhone and that one is created as a proxy, not the
|
||||
// original object when the find on Client is called. However loading proxies did not work correctly.
|
||||
$this->assertType('Doctrine\Tests\ORM\Functional\Ticket\DDC440Phone', $p1);
|
||||
$this->assertInstanceOf('Doctrine\Tests\ORM\Functional\Ticket\DDC440Phone', $p1);
|
||||
$originalData = $uw->getOriginalEntityData($p1);
|
||||
$this->assertEquals($phone->getNumber(), $originalData['number']);
|
||||
|
||||
|
||||
//If you comment out previous test, this one should pass
|
||||
$this->assertType('Doctrine\Tests\ORM\Functional\Ticket\DDC440Phone', $p2);
|
||||
$this->assertInstanceOf('Doctrine\Tests\ORM\Functional\Ticket\DDC440Phone', $p2);
|
||||
$originalData = $uw->getOriginalEntityData($p2);
|
||||
$this->assertEquals($phone2->getNumber(), $originalData['number']);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class DDC501Test extends OrmFunctionalTestCase
|
||||
|
||||
// freeze and unfreeze
|
||||
$userClone = unserialize(serialize($userReloaded));
|
||||
$this->assertType('Doctrine\Tests\Models\CMS\CmsUser', $userClone);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $userClone);
|
||||
|
||||
// detached user can't know about his phonenumbers
|
||||
$this->assertEquals(0, count($userClone->getPhonenumbers()));
|
||||
|
||||
@@ -66,7 +66,7 @@ class DDC633Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$appointments = $this->_em->createQuery("SELECT a FROM " . __NAMESPACE__ . "\DDC633Appointment a")->getResult();
|
||||
|
||||
foreach ($appointments AS $eagerAppointment) {
|
||||
$this->assertType('Doctrine\ORM\Proxy\Proxy', $eagerAppointment->patient);
|
||||
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $eagerAppointment->patient);
|
||||
$this->assertTrue($eagerAppointment->patient->__isInitialized__, "Proxy should already be initialized due to eager loading!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@ class DDC729Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$a = new DDC729A();
|
||||
$a->id = $aId;
|
||||
|
||||
$this->assertType('Doctrine\Common\Collections\ArrayCollection', $a->related);
|
||||
$this->assertInstanceOf('Doctrine\Common\Collections\ArrayCollection', $a->related);
|
||||
|
||||
$a = $this->_em->merge($a);
|
||||
|
||||
$this->assertType('Doctrine\ORM\PersistentCollection', $a->related);
|
||||
$this->assertInstanceOf('Doctrine\ORM\PersistentCollection', $a->related);
|
||||
|
||||
$this->assertFalse($a->related->isInitialized(), "Collection should not be marked initialized.");
|
||||
$this->assertFalse($a->related->isDirty(), "Collection should not be marked as dirty.");
|
||||
|
||||
@@ -72,7 +72,7 @@ class DDC736Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
/* @var $cart2 Doctrine\Tests\Models\ECommerce\ECommerceCart */
|
||||
$cart2 = $result[0][0];
|
||||
$this->assertType('Doctrine\ORM\Proxy\Proxy', $cart2->getCustomer());
|
||||
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $cart2->getCustomer());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@ class DDC748Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_em->persist($article);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->assertType('Doctrine\Common\Collections\Collection', $user->articles);
|
||||
$this->assertInstanceOf('Doctrine\Common\Collections\Collection', $user->articles);
|
||||
$this->_em->refresh($article);
|
||||
$this->assertTrue($article !== $user->articles, "The article should not be replaced on the inverse side of the relation.");
|
||||
$this->assertType('Doctrine\Common\Collections\Collection', $user->articles);
|
||||
$this->assertInstanceOf('Doctrine\Common\Collections\Collection', $user->articles);
|
||||
}
|
||||
|
||||
public function testRefreshOneToOne()
|
||||
|
||||
@@ -52,20 +52,20 @@ class DDC837Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
// Test Class1
|
||||
$e1 = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC837Super', $c1->id);
|
||||
|
||||
$this->assertType('Doctrine\Tests\ORM\Functional\Ticket\DDC837Class1', $e1);
|
||||
$this->assertInstanceOf('Doctrine\Tests\ORM\Functional\Ticket\DDC837Class1', $e1);
|
||||
$this->assertEquals('Foo', $e1->title);
|
||||
$this->assertEquals('Foo', $e1->description);
|
||||
$this->assertType(__NAMESPACE__ . '\DDC837Aggregate', $e1->aggregate);
|
||||
$this->assertInstanceOf(__NAMESPACE__ . '\DDC837Aggregate', $e1->aggregate);
|
||||
$this->assertEquals('test1', $e1->aggregate->getSysname());
|
||||
|
||||
// Test Class 2
|
||||
$e2 = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC837Super', $c2->id);
|
||||
|
||||
$this->assertType('Doctrine\Tests\ORM\Functional\Ticket\DDC837Class2', $e2);
|
||||
$this->assertInstanceOf('Doctrine\Tests\ORM\Functional\Ticket\DDC837Class2', $e2);
|
||||
$this->assertEquals('Bar', $e2->title);
|
||||
$this->assertEquals('Bar', $e2->description);
|
||||
$this->assertEquals('Bar', $e2->text);
|
||||
$this->assertType(__NAMESPACE__ . '\DDC837Aggregate', $e2->aggregate);
|
||||
$this->assertInstanceOf(__NAMESPACE__ . '\DDC837Aggregate', $e2->aggregate);
|
||||
$this->assertEquals('test2', $e2->aggregate->getSysname());
|
||||
|
||||
$all = $this->_em->getRepository(__NAMESPACE__.'\DDC837Super')->findAll();
|
||||
|
||||
@@ -34,10 +34,10 @@ class DDC949Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$true = $this->_em->getRepository('Doctrine\Tests\Models\Generic\BooleanModel')->findOneBy(array('booleanField' => true));
|
||||
$false = $this->_em->getRepository('Doctrine\Tests\Models\Generic\BooleanModel')->findOneBy(array('booleanField' => false));
|
||||
|
||||
$this->assertType('Doctrine\Tests\Models\Generic\BooleanModel', $true);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Generic\BooleanModel', $true);
|
||||
$this->assertTrue($true->booleanField, "True Boolean Model should be true.");
|
||||
|
||||
$this->assertType('Doctrine\Tests\Models\Generic\BooleanModel', $false);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\Generic\BooleanModel', $false);
|
||||
$this->assertFalse($false->booleanField, "False Boolean Model should be false.");
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,9 @@ class TypeTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->assertInstanceOf('DateTime', $dateTimeDb->datetime);
|
||||
$this->assertEquals('2009-10-02 20:10:52', $dateTimeDb->datetime->format('Y-m-d H:i:s'));
|
||||
|
||||
$articles = $this->_em->getRepository( 'Doctrine\Tests\Models\Generic\DateTimeModel' )->findBy( array( 'datetime' => new \DateTime( "now" ) ) );
|
||||
$this->assertEquals( 0, count( $articles ) );
|
||||
}
|
||||
|
||||
public function testDqlQueryBindDateTimeInstance()
|
||||
@@ -172,4 +175,4 @@ class TypeTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertInstanceOf('DateTime', $dateTime->time);
|
||||
$this->assertEquals('19:27:20', $dateTime->time->format('H:i:s'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,4 +763,58 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
|
||||
$this->assertEquals(1, count($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1358
|
||||
*/
|
||||
public function testMissingIdForRootEntity()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
|
||||
// Faked result set
|
||||
$resultSet = array(
|
||||
//row1
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
array(
|
||||
'u__id' => null,
|
||||
'u__status' => null,
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
),
|
||||
array(
|
||||
'u__id' => null,
|
||||
'u__status' => null,
|
||||
'sclr0' => 'JWAGE',
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(4, count($result), "Should hydrate four results.");
|
||||
|
||||
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
|
||||
$this->assertEquals('ROMANB', $result[1]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[2]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[3]['nameUpper']);
|
||||
|
||||
$this->assertEquals(array('id' => 1, 'status' => 'developer'), $result[0][0]);
|
||||
$this->assertNull($result[1][0]);
|
||||
$this->assertEquals(array('id' => 2, 'status' => 'developer'), $result[2][0]);
|
||||
$this->assertNull($result[3][0]);
|
||||
}
|
||||
}
|
||||
@@ -1008,4 +1008,165 @@ class ObjectHydratorTest extends HydrationTestCase
|
||||
$this->assertEquals(4, count($result[1]->groups));
|
||||
$this->assertEquals(2, count($result[1]->phonenumbers));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1358
|
||||
*/
|
||||
public function testMissingIdForRootEntity()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
|
||||
// Faked result set
|
||||
$resultSet = array(
|
||||
//row1
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
array(
|
||||
'u__id' => null,
|
||||
'u__status' => null,
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
),
|
||||
array(
|
||||
'u__id' => null,
|
||||
'u__status' => null,
|
||||
'sclr0' => 'JWAGE',
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm, array(Query::HINT_FORCE_PARTIAL_LOAD => true));
|
||||
|
||||
$this->assertEquals(4, count($result), "Should hydrate four results.");
|
||||
|
||||
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
|
||||
$this->assertEquals('ROMANB', $result[1]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[2]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[3]['nameUpper']);
|
||||
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0][0]);
|
||||
$this->assertNull($result[1][0]);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[2][0]);
|
||||
$this->assertNull($result[3][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1358
|
||||
* @return void
|
||||
*/
|
||||
public function testMissingIdForCollectionValuedChildEntity()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
|
||||
'p',
|
||||
'u',
|
||||
'phonenumbers'
|
||||
);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
$rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber');
|
||||
|
||||
// Faked result set
|
||||
$resultSet = array(
|
||||
//row1
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
'p__phonenumber' => '42',
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
'p__phonenumber' => null
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
'p__phonenumber' => '91'
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'JWAGE',
|
||||
'p__phonenumber' => null
|
||||
)
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm, array(Query::HINT_FORCE_PARTIAL_LOAD => true));
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertEquals(1, $result[0][0]->phonenumbers->count());
|
||||
$this->assertEquals(1, $result[1][0]->phonenumbers->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1358
|
||||
*/
|
||||
public function testMissingIdForSingleValuedChildEntity()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addJoinedEntityResult(
|
||||
'Doctrine\Tests\Models\CMS\CmsAddress',
|
||||
'a',
|
||||
'u',
|
||||
'address'
|
||||
);
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
$rsm->addFieldResult('a', 'a__id', 'id');
|
||||
$rsm->addFieldResult('a', 'a__city', 'city');
|
||||
$rsm->addMetaResult('a', 'user_id', 'user_id');
|
||||
|
||||
// Faked result set
|
||||
$resultSet = array(
|
||||
//row1
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
'a__id' => 1,
|
||||
'a__city' => 'Berlin',
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'BENJAMIN',
|
||||
'a__id' => null,
|
||||
'a__city' => null,
|
||||
),
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm, array(Query::HINT_FORCE_PARTIAL_LOAD => true));
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress', $result[0][0]->address);
|
||||
$this->assertNull($result[1][0]->address);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use Doctrine\Tests\Mocks\ConnectionMock;
|
||||
use Doctrine\Tests\Mocks\DriverMock;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\Common\EventManager;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
@@ -81,6 +82,51 @@ class ClassMetadataFactoryTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertFalse($h2);
|
||||
$this->assertTrue($h1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1512
|
||||
*/
|
||||
public function testIsTransient()
|
||||
{
|
||||
$cmf = new ClassMetadataFactory();
|
||||
$driver = $this->getMock('Doctrine\ORM\Mapping\Driver\Driver');
|
||||
$driver->expects($this->at(0))
|
||||
->method('isTransient')
|
||||
->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsUser'))
|
||||
->will($this->returnValue(true));
|
||||
$driver->expects($this->at(1))
|
||||
->method('isTransient')
|
||||
->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsArticle'))
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$em = $this->_createEntityManager($driver);
|
||||
|
||||
$this->assertTrue($em->getMetadataFactory()->isTransient('Doctrine\Tests\Models\CMS\CmsUser'));
|
||||
$this->assertFalse($em->getMetadataFactory()->isTransient('Doctrine\Tests\Models\CMS\CmsArticle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1512
|
||||
*/
|
||||
public function testIsTransientEntityNamespace()
|
||||
{
|
||||
$cmf = new ClassMetadataFactory();
|
||||
$driver = $this->getMock('Doctrine\ORM\Mapping\Driver\Driver');
|
||||
$driver->expects($this->at(0))
|
||||
->method('isTransient')
|
||||
->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsUser'))
|
||||
->will($this->returnValue(true));
|
||||
$driver->expects($this->at(1))
|
||||
->method('isTransient')
|
||||
->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsArticle'))
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$em = $this->_createEntityManager($driver);
|
||||
$em->getConfiguration()->addEntityNamespace('CMS', 'Doctrine\Tests\Models\CMS');
|
||||
|
||||
$this->assertTrue($em->getMetadataFactory()->isTransient('CMS:CmsUser'));
|
||||
$this->assertFalse($em->getMetadataFactory()->isTransient('CMS:CmsArticle'));
|
||||
}
|
||||
|
||||
protected function _createEntityManager($metadataDriver)
|
||||
{
|
||||
|
||||
@@ -33,6 +33,24 @@ class XmlMappingDriverTest extends AbstractMappingDriverTest
|
||||
$this->assertEquals($expectedMap, $class->discriminatorMap);
|
||||
}
|
||||
|
||||
public function testIdentifierWithAssociationKey()
|
||||
{
|
||||
$driver = $this->_loadDriver();
|
||||
$em = $this->_getTestEntityManager();
|
||||
$factory = new \Doctrine\ORM\Mapping\ClassMetadataFactory();
|
||||
|
||||
$em->getConfiguration()->setMetadataDriverImpl($driver);
|
||||
$factory->setEntityManager($em);
|
||||
|
||||
$class = $factory->getMetadataFor('Doctrine\Tests\Models\DDC117\DDC117Translation');
|
||||
|
||||
$this->assertEquals(array('language', 'article'), $class->identifier);
|
||||
$this->assertArrayHasKey('article', $class->associationMappings);
|
||||
|
||||
$this->assertArrayHasKey('id', $class->associationMappings['article']);
|
||||
$this->assertTrue($class->associationMappings['article']['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $xmlMappingFile
|
||||
* @dataProvider dataValidSchema
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
|
||||
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||
|
||||
<entity name="Doctrine\Tests\Models\DDC117\DDC117Translation">
|
||||
<many-to-one field="article" target-entity="DDC117Article">
|
||||
<join-column name="article_id" referenced-column-name="article_id" />
|
||||
</many-to-one>
|
||||
|
||||
<many-to-many field="reviewedByEditors" target-entity="DDC117Editor" mapped-by="reviewingTranslations" />
|
||||
|
||||
<one-to-many field="lastTranslatedBy" target-entity="DDC117Editor" mapped-by="lastTranslation" />
|
||||
|
||||
<id name="article" association-key="true" />
|
||||
<id name="language" type="string" />
|
||||
|
||||
<field name="title" type="string" />
|
||||
</entity>
|
||||
|
||||
</doctrine-mapping>
|
||||
@@ -39,7 +39,7 @@
|
||||
<join-column name="address_id" referenced-column-name="id" on-delete="CASCADE" on-update="CASCADE"/>
|
||||
</one-to-one>
|
||||
|
||||
<one-to-many field="phonenumbers" target-entity="Phonenumber" mapped-by="user" orphan-removal="true">
|
||||
<one-to-many field="phonenumbers" target-entity="Phonenumber" mapped-by="user" index-by="number" orphan-removal="true">
|
||||
<cascade>
|
||||
<cascade-persist/>
|
||||
</cascade>
|
||||
|
||||
@@ -90,4 +90,28 @@ class QueryTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertEquals('baz', $q->getHint('bar'));
|
||||
$this->assertEquals(array('foo' => 'bar', 'bar' => 'baz'), $q->getHints());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Doctrine\ORM\Query\QueryException
|
||||
**/
|
||||
public function testIterateWithNoDistinctAndWrongSelectClause()
|
||||
{
|
||||
$q = $this->_em->createQuery("select u, a from Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.articles a");
|
||||
$q->iterate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Doctrine\ORM\Query\QueryException
|
||||
**/
|
||||
public function testIterateWithNoDistinctAndWithValidSelectClause()
|
||||
{
|
||||
$q = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.articles a");
|
||||
$q->iterate();
|
||||
}
|
||||
|
||||
public function testIterateWithDistinct()
|
||||
{
|
||||
$q = $this->_em->createQuery("SELECT DISTINCT u from Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.articles a");
|
||||
$q->iterate();
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
}
|
||||
|
||||
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
|
||||
->useQueryCache(false);
|
||||
->useQueryCache(false);
|
||||
|
||||
foreach ($queryHints AS $name => $value) {
|
||||
$query->setHint($name, $value);
|
||||
@@ -54,7 +54,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
* @param array $queryHints
|
||||
* @param array $queryParams
|
||||
*/
|
||||
public function assertInvalidSqlGeneration($dqlToBeTested, $expectedException, array $queryHints = array(), array $queryParams = array())
|
||||
public function assertInvalidSqlGeneration($dqlToBeTested, $expectedException, array $queryHints = array(Query::HINT_FORCE_PARTIAL_LOAD => true), array $queryParams = array())
|
||||
{
|
||||
$this->setExpectedException($expectedException);
|
||||
|
||||
@@ -65,7 +65,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
}
|
||||
|
||||
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
|
||||
->useQueryCache(false);
|
||||
->useQueryCache(false);
|
||||
|
||||
foreach ($queryHints AS $name => $value) {
|
||||
$query->setHint($name, $value);
|
||||
@@ -596,7 +596,24 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
. ' WHERE EXISTS ('
|
||||
. 'SELECT c1_.id FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id'
|
||||
. ')'
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
public function testExistsExpressionWithSimpleSelectReturningScalar()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
// DQL
|
||||
// The result of this query consists of all employees whose spouses are also employees.
|
||||
'SELECT DISTINCT emp FROM Doctrine\Tests\Models\CMS\CmsEmployee emp
|
||||
WHERE EXISTS (
|
||||
SELECT 1
|
||||
FROM Doctrine\Tests\Models\CMS\CmsEmployee spouseEmp
|
||||
WHERE spouseEmp = emp.spouse)',
|
||||
// SQL
|
||||
'SELECT DISTINCT c0_.id AS id0, c0_.name AS name1 FROM cms_employees c0_'
|
||||
. ' WHERE EXISTS ('
|
||||
. 'SELECT 1 AS sclr2 FROM cms_employees c1_ WHERE c1_.id = c0_.spouse_id'
|
||||
. ')'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -933,6 +950,169 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
"SELECT d0_.article_id AS article_id0, d0_.title AS title1, d1_.article_id AS article_id2, d1_.title AS title3 FROM DDC117Link d2_ INNER JOIN DDC117Article d0_ ON d2_.target_id = d0_.article_id INNER JOIN DDC117Article d1_ ON d2_.source_id = d1_.article_id"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInRootClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c1_.car_id AS car_id3, c2_.salary AS salary4, c2_.department AS department5, c2_.startDate AS startDate6, c0_.discr AS discr7, c0_.spouse_id AS spouse_id8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInRootClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInChildClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c2_.car_id AS car_id6, c0_.discr AS discr7, c0_.spouse_id AS spouse_id8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
public function testSubSelectAliasesFromOuterQueryReuseInWhereClause()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT uo, (SELECT ui.name FROM Doctrine\Tests\Models\CMS\CmsUser ui WHERE ui.id = uo.id) AS bar FROM Doctrine\Tests\Models\CMS\CmsUser uo WHERE bar = ?0",
|
||||
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, (SELECT c1_.name FROM cms_users c1_ WHERE c1_.id = c0_.id) AS sclr4 FROM cms_users c0_ WHERE sclr4 = ?"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInChildClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c0_.discr AS discr5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInLeafClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c0_.discr AS discr6, c0_.spouse_id AS spouse_id7, c2_.car_id AS car_id8 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeJoinInLeafClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m',
|
||||
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c0_.discr AS discr6 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id',
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInRootClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6, c0_.salesPerson_id AS salesPerson_id7 FROM company_contracts c0_ WHERE c0_.discr IN ('fix', 'flexible', 'flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInRootClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6 FROM company_contracts c0_ WHERE c0_.discr IN ('fix', 'flexible', 'flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInChildClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT fc FROM Doctrine\Tests\Models\Company\CompanyFlexContract fc',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5, c0_.salesPerson_id AS salesPerson_id6 FROM company_contracts c0_ WHERE c0_.discr IN ('flexible', 'flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInChildClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT fc FROM Doctrine\Tests\Models\Company\CompanyFlexContract fc',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5 FROM company_contracts c0_ WHERE c0_.discr IN ('flexible', 'flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInLeafClassWithDisabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT fuc FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract fuc',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5, c0_.salesPerson_id AS salesPerson_id6 FROM company_contracts c0_ WHERE c0_.discr IN ('flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1389
|
||||
*/
|
||||
public function testInheritanceTypeSingleTableInLeafClassWithEnabledForcePartialLoad()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT fuc FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract fuc',
|
||||
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5 FROM company_contracts c0_ WHERE c0_.discr IN ('flexultra')",
|
||||
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1435
|
||||
*/
|
||||
public function testForeignKeyAsPrimaryKeySubselect()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT s FROM Doctrine\Tests\Models\DDC117\DDC117Article s WHERE EXISTS (SELECT r FROM Doctrine\Tests\Models\DDC117\DDC117Reference r WHERE r.source = s)",
|
||||
"SELECT d0_.article_id AS article_id0, d0_.title AS title1 FROM DDC117Article d0_ WHERE EXISTS (SELECT d1_.source_id, d1_.target_id FROM DDC117Reference d1_ WHERE d1_.source_id = d0_.article_id)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -732,4 +732,17 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
|
||||
|
||||
$this->assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $qb->getDQL());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1619
|
||||
*/
|
||||
public function testAddDistinct()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder()
|
||||
->select('u')
|
||||
->distinct()
|
||||
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
|
||||
$this->assertEquals('SELECT DISTINCT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $qb->getDQL());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,14 +133,14 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
|
||||
public function testExportedMetadataCanBeReadBackIn()
|
||||
{
|
||||
$type = $this->_getType();
|
||||
|
||||
|
||||
$metadataDriver = $this->_createMetadataDriver($type, __DIR__ . '/export/' . $type);
|
||||
$em = $this->_createEntityManager($metadataDriver);
|
||||
$cmf = $this->_createClassMetadataFactory($em, $type);
|
||||
$metadata = $cmf->getAllMetadata();
|
||||
|
||||
$class = current($metadata);
|
||||
|
||||
|
||||
$this->assertEquals('Doctrine\Tests\ORM\Tools\Export\ExportedUser', $class->name);
|
||||
|
||||
return $class;
|
||||
@@ -217,7 +217,6 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
|
||||
$this->assertEquals('address_id', $class->associationMappings['address']['joinColumns'][0]['name']);
|
||||
$this->assertEquals('id', $class->associationMappings['address']['joinColumns'][0]['referencedColumnName']);
|
||||
$this->assertEquals('CASCADE', $class->associationMappings['address']['joinColumns'][0]['onDelete']);
|
||||
$this->assertEquals('CASCADE', $class->associationMappings['address']['joinColumns'][0]['onUpdate']);
|
||||
|
||||
$this->assertTrue($class->associationMappings['address']['isCascadeRemove']);
|
||||
$this->assertTrue($class->associationMappings['address']['isCascadePersist']);
|
||||
@@ -247,7 +246,7 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
|
||||
$this->assertTrue($class->associationMappings['phonenumbers']['isCascadeMerge']);
|
||||
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeDetach']);
|
||||
$this->assertTrue($class->associationMappings['phonenumbers']['orphanRemoval']);
|
||||
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace Doctrine\Tests;
|
||||
|
||||
use Doctrine\Common\Cache\ArrayCache;
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Doctrine\Common\Annotations\SimpleAnnotationReader;
|
||||
|
||||
/**
|
||||
* Base testcase class for all ORM testcases.
|
||||
@@ -20,10 +22,13 @@ abstract class OrmTestCase extends DoctrineTestCase
|
||||
*/
|
||||
protected function createAnnotationDriver($paths = array(), $alias = null)
|
||||
{
|
||||
if (version_compare(\Doctrine\Common\Version::VERSION, '3.0.0', '>=')) {
|
||||
$reader = new \Doctrine\Common\Annotations\CachedReader(
|
||||
new \Doctrine\Common\Annotations\AnnotationReader(), new ArrayCache()
|
||||
);
|
||||
if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
|
||||
// Register the ORM Annotations in the AnnotationRegistry
|
||||
AnnotationRegistry::registerFile(__DIR__ . '/../../../lib/Doctrine/ORM//Mapping/Driver/DoctrineAnnotations.php');
|
||||
|
||||
$reader = new SimpleAnnotationReader();
|
||||
$reader->addNamespace('Doctrine\ORM\Mapping');
|
||||
$reader = new \Doctrine\Common\Annotations\CachedReader($reader, new ArrayCache());
|
||||
} else if (version_compare(\Doctrine\Common\Version::VERSION, '2.1.0-BETA3-DEV', '>=')) {
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
|
||||
$reader->setIgnoreNotImportedAnnotations(true);
|
||||
@@ -46,10 +51,10 @@ abstract class OrmTestCase extends DoctrineTestCase
|
||||
}
|
||||
return new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, (array)$paths);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an EntityManager for testing purposes.
|
||||
*
|
||||
*
|
||||
* NOTE: The created EntityManager will have its dependant DBAL parts completely
|
||||
* mocked out using a DriverMock, ConnectionMock, etc. These mocks can then
|
||||
* be configured in the tests to simulate the DBAL behavior that is desired
|
||||
@@ -93,7 +98,7 @@ abstract class OrmTestCase extends DoctrineTestCase
|
||||
}
|
||||
return self::$_metadataCacheImpl;
|
||||
}
|
||||
|
||||
|
||||
private static function getSharedQueryCacheImpl()
|
||||
{
|
||||
if (self::$_queryCacheImpl === null) {
|
||||
|
||||
32
tests/travis/mysql.travis.xml
Normal file
32
tests/travis/mysql.travis.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<phpunit>
|
||||
<php>
|
||||
<var name="db_type" value="pdo_mysql"/>
|
||||
<var name="db_host" value="localhost" />
|
||||
<var name="db_username" value="travis" />
|
||||
<var name="db_password" value="" />
|
||||
<var name="db_name" value="doctrine_tests" />
|
||||
<var name="db_port" value="3306"/>
|
||||
|
||||
<var name="tmpdb_type" value="pdo_mysql"/>
|
||||
<var name="tmpdb_host" value="localhost" />
|
||||
<var name="tmpdb_username" value="travis" />
|
||||
<var name="tmpdb_password" value="" />
|
||||
<var name="tmpdb_name" value="doctrine_tests_tmp" />
|
||||
<var name="tmpdb_port" value="3306"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Doctrine Test Suite">
|
||||
<directory>./../Doctrine/Tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>performance</group>
|
||||
<group>locking_functional</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
|
||||
</phpunit>
|
||||
|
||||
29
tests/travis/pgsql.travis.xml
Normal file
29
tests/travis/pgsql.travis.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<phpunit>
|
||||
<php>
|
||||
<var name="db_type" value="pdo_pgsql"/>
|
||||
<var name="db_host" value="localhost" />
|
||||
<var name="db_username" value="postgres" />
|
||||
<var name="db_password" value="" />
|
||||
<var name="db_name" value="doctrine_tests" />
|
||||
<var name="db_port" value="5432"/>
|
||||
|
||||
<var name="tmpdb_type" value="pdo_pgsql"/>
|
||||
<var name="tmpdb_host" value="localhost" />
|
||||
<var name="tmpdb_username" value="postgres" />
|
||||
<var name="tmpdb_password" value="" />
|
||||
<var name="tmpdb_name" value="doctrine_tests_tmp" />
|
||||
<var name="tmpdb_port" value="5432"/>
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Doctrine Test Suite">
|
||||
<directory>./../Doctrine/Tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>performance</group>
|
||||
<group>locking_functional</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
</phpunit>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user