mirror of
https://github.com/doctrine/orm.git
synced 2026-03-23 22:42:18 +01:00
Merge branch '3.5.x' into 3.6.x
* 3.5.x: Add a CI job that fails on deprecations (#12188) use the empty string instead of null as an array offset (#12181) do not call setAccessible() on PHP >= 8.1 (#12182) Fix docs on final entities (#12176) Remove Database and Model First chapters that said little of value. Switch to IgnoreDeprecations docs: consistent PostgreSQL's name case docs: generation strategies differences between DBAL 3 and 4 Check extra condition to decide if a test was skipped Use PHPUnit 11 when possible Migrate away from annotations in tests Migrate away from assertStringNotMatchesFormat() Migrate to willReturn() Migrate away from getMockForAbstractClass() Fix `IN`/`NOT IN` expression handling and support enums when matching on to-many-collections
This commit is contained in:
72
.github/workflows/continuous-integration.yml
vendored
72
.github/workflows/continuous-integration.yml
vendored
@@ -115,8 +115,24 @@ jobs:
|
||||
ENABLE_SECOND_LEVEL_CACHE: 0
|
||||
ENABLE_NATIVE_LAZY_OBJECTS: ${{ matrix.native_lazy }}
|
||||
|
||||
- name: "Run PHPUnit with Second Level Cache"
|
||||
run: "vendor/bin/phpunit -c ci/github/phpunit/${{ matrix.extension }}.xml --exclude-group performance,non-cacheable,locking_functional --coverage-clover=coverage-cache.xml"
|
||||
- name: "Run PHPUnit with Second Level Cache and PHPUnit 10"
|
||||
run: |
|
||||
vendor/bin/phpunit -c ci/github/phpunit/${{ matrix.extension }}.xml \
|
||||
--exclude-group=performance,non-cacheable,locking_functional \
|
||||
--coverage-clover=coverage-cache.xml
|
||||
if: "${{ matrix.php-version == '8.1' }}"
|
||||
env:
|
||||
ENABLE_SECOND_LEVEL_CACHE: 1
|
||||
ENABLE_NATIVE_LAZY_OBJECTS: ${{ matrix.native_lazy }}
|
||||
|
||||
- name: "Run PHPUnit with Second Level Cache and PHPUnit 11+"
|
||||
run: |
|
||||
vendor/bin/phpunit -c ci/github/phpunit/${{ matrix.extension }}.xml \
|
||||
--exclude-group=performance \
|
||||
--exclude-group=non-cacheable \
|
||||
--exclude-group=locking_functional \
|
||||
--coverage-clover=coverage-cache.xml
|
||||
if: "${{ matrix.php-version != '8.1' }}"
|
||||
env:
|
||||
ENABLE_SECOND_LEVEL_CACHE: 1
|
||||
ENABLE_NATIVE_LAZY_OBJECTS: ${{ matrix.native_lazy }}
|
||||
@@ -128,6 +144,40 @@ jobs:
|
||||
path: "coverage*.xml"
|
||||
|
||||
|
||||
phpunit-deprecations:
|
||||
name: "PHPUnit (fail on deprecations)"
|
||||
runs-on: "ubuntu-24.04"
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v5"
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: "Install PHP"
|
||||
uses: "shivammathur/setup-php@v2"
|
||||
with:
|
||||
php-version: "8.5"
|
||||
extensions: "apcu, pdo, sqlite3"
|
||||
coverage: "pcov"
|
||||
ini-values: "zend.assertions=1, apc.enable_cli=1"
|
||||
|
||||
- name: "Allow dev dependencies"
|
||||
run: composer config minimum-stability dev
|
||||
|
||||
- name: "Install dependencies with Composer"
|
||||
uses: "ramsey/composer-install@v3"
|
||||
with:
|
||||
composer-options: "--ignore-platform-req=php+"
|
||||
dependency-versions: "highest"
|
||||
|
||||
- name: "Run PHPUnit"
|
||||
run: "vendor/bin/phpunit -c ci/github/phpunit/sqlite3.xml --fail-on-deprecation"
|
||||
env:
|
||||
ENABLE_SECOND_LEVEL_CACHE: 0
|
||||
ENABLE_NATIVE_LAZY_OBJECTS: 1
|
||||
|
||||
|
||||
phpunit-postgres:
|
||||
name: "PHPUnit with PostgreSQL"
|
||||
runs-on: "ubuntu-22.04"
|
||||
@@ -339,8 +389,22 @@ jobs:
|
||||
env:
|
||||
ENABLE_SECOND_LEVEL_CACHE: 0
|
||||
|
||||
- name: "Run PHPUnit with Second Level Cache"
|
||||
run: "vendor/bin/phpunit -c ci/github/phpunit/${{ matrix.extension }}.xml --exclude-group performance,non-cacheable,locking_functional --coverage-clover=coverage-no-cache.xml"
|
||||
- name: "Run PHPUnit with Second Level Cache and PHPUnit 10"
|
||||
run: |
|
||||
vendor/bin/phpunit -c ci/github/phpunit/${{ matrix.extension }}.xml \
|
||||
--exclude-group=performance,non-cacheable,locking_functional \
|
||||
--coverage-clover=coverage-no-cache.xml"
|
||||
if: "${{ matrix.php-version == '8.1' }}"
|
||||
env:
|
||||
ENABLE_SECOND_LEVEL_CACHE: 1
|
||||
- name: "Run PHPUnit with Second Level Cache and PHPUnit 11+"
|
||||
run: |
|
||||
vendor/bin/phpunit -c ci/github/phpunit/${{ matrix.extension }}.xml \
|
||||
--exclude-group=performance \
|
||||
--exclude-group=non-cacheable \
|
||||
--exclude-group=locking_functional \
|
||||
--coverage-clover=coverage-no-cache.xml
|
||||
if: "${{ matrix.php-version != '8.1' }}"
|
||||
env:
|
||||
ENABLE_SECOND_LEVEL_CACHE: 1
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"phpstan/extension-installer": "^1.4",
|
||||
"phpstan/phpstan": "2.1.22",
|
||||
"phpstan/phpstan-deprecation-rules": "^2",
|
||||
"phpunit/phpunit": "^10.4.0",
|
||||
"phpunit/phpunit": "^10.5.0 || ^11.5",
|
||||
"psr/log": "^1 || ^2 || ^3",
|
||||
"squizlabs/php_codesniffer": "3.13.2",
|
||||
"symfony/cache": "^5.4 || ^6.2 || ^7.0 || ^8.0"
|
||||
|
||||
@@ -76,6 +76,8 @@ Configuration Options
|
||||
The following sections describe all the configuration options
|
||||
available on a ``Doctrine\ORM\Configuration`` instance.
|
||||
|
||||
.. _reference-native-lazy-objects:
|
||||
|
||||
Native Lazy Objects (**OPTIONAL**)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -79,8 +79,9 @@ Entities
|
||||
An entity is a lightweight, persistent domain object. An entity can
|
||||
be any regular PHP class observing the following restrictions:
|
||||
|
||||
- An entity class must not be final nor read-only but
|
||||
it may contain final methods or read-only properties.
|
||||
- An entity class can be final or read-only when
|
||||
you use :ref:`native lazy objects <reference-native-lazy-objects>`.
|
||||
It may contain final methods or read-only properties too.
|
||||
- Any two entity classes in a class hierarchy that inherit
|
||||
directly or indirectly from one another must not have a mapped
|
||||
property with the same name. That is, if B inherits from A then B
|
||||
|
||||
@@ -389,17 +389,19 @@ Here is the list of possible generation strategies:
|
||||
|
||||
- ``AUTO`` (default): Tells Doctrine to pick the strategy that is
|
||||
preferred by the used database platform. The preferred strategies
|
||||
are ``IDENTITY`` for MySQL, SQLite, MsSQL and SQL Anywhere and, for
|
||||
historical reasons, ``SEQUENCE`` for Oracle and PostgreSQL. This
|
||||
strategy provides full portability.
|
||||
are ``IDENTITY`` for MySQL, SQLite, MsSQL, SQL Anywhere and
|
||||
PostgreSQL (on DBAL 4) and, for historical reasons, ``SEQUENCE``
|
||||
for Oracle and PostgreSQL (on DBAL 3). This strategy provides
|
||||
full portability.
|
||||
- ``IDENTITY``: Tells Doctrine to use special identity columns in
|
||||
the database that generate a value on insertion of a row. This
|
||||
strategy does currently not provide full portability and is
|
||||
supported by the following platforms: MySQL/SQLite/SQL Anywhere
|
||||
(``AUTO_INCREMENT``), MSSQL (``IDENTITY``) and PostgreSQL (``SERIAL``).
|
||||
(``AUTO_INCREMENT``), MSSQL (``IDENTITY``) and PostgreSQL (``SERIAL``
|
||||
on DBAL 3, ``GENERATED BY DEFAULT AS IDENTITY`` on DBAL 4).
|
||||
- ``SEQUENCE``: Tells Doctrine to use a database sequence for ID
|
||||
generation. This strategy does currently not provide full
|
||||
portability. Sequences are supported by Oracle, PostgreSql and
|
||||
portability. Sequences are supported by Oracle, PostgreSQL and
|
||||
SQL Anywhere.
|
||||
- ``NONE``: Tells Doctrine that the identifiers are assigned (and
|
||||
thus generated) by your code. The assignment must take place before
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
:depth: 3
|
||||
|
||||
tutorials/getting-started
|
||||
tutorials/getting-started-database
|
||||
tutorials/getting-started-models
|
||||
tutorials/working-with-indexed-associations
|
||||
tutorials/extra-lazy-associations
|
||||
tutorials/composite-primary-keys
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
Getting Started: Database First
|
||||
===============================
|
||||
|
||||
.. note:: *Development Workflows*
|
||||
|
||||
When you :doc:`Code First <getting-started>`, you
|
||||
start with developing Objects and then map them onto your database. When
|
||||
you :doc:`Model First <getting-started-models>`, you are modelling your application using tools (for
|
||||
example UML) and generate database schema and PHP code from this model.
|
||||
When you have a Database First, you already have a database schema
|
||||
and generate the corresponding PHP code from it.
|
||||
|
||||
.. note::
|
||||
|
||||
This getting started guide is in development.
|
||||
|
||||
Development of new applications often starts with an existing database schema.
|
||||
When the database schema is the starting point for your application, then
|
||||
development is said to use the *Database First* approach to Doctrine.
|
||||
|
||||
In this workflow you would modify the database schema first and then
|
||||
regenerate the PHP code to use with this schema. You need a flexible
|
||||
code-generator for this task.
|
||||
|
||||
We spun off a subproject, Doctrine CodeGenerator, that will fill this gap and
|
||||
allow you to do *Database First* development.
|
||||
@@ -1,24 +0,0 @@
|
||||
Getting Started: Model First
|
||||
============================
|
||||
|
||||
.. note:: *Development Workflows*
|
||||
|
||||
When you :doc:`Code First <getting-started>`, you
|
||||
start with developing Objects and then map them onto your database. When
|
||||
you Model First, you are modelling your application using tools (for
|
||||
example UML) and generate database schema and PHP code from this model.
|
||||
When you have a :doc:`Database First <getting-started-database>`, then you already have a database schema
|
||||
and generate the corresponding PHP code from it.
|
||||
|
||||
.. note::
|
||||
|
||||
This getting started guide is in development.
|
||||
|
||||
There are applications when you start with a high-level description of the
|
||||
model using modelling tools such as UML. Modelling tools could also be Excel,
|
||||
XML or CSV files that describe the model in some structured way. If your
|
||||
application is using a modelling tool, then the development workflow is said to
|
||||
be a *Model First* approach to Doctrine2.
|
||||
|
||||
In this workflow you always change the model description and then regenerate
|
||||
both PHP code and database schema from this model.
|
||||
@@ -49,8 +49,9 @@ An entity contains persistable properties. A persistable property
|
||||
is an instance variable of the entity that is saved into and retrieved from the database
|
||||
by Doctrine's data mapping capabilities.
|
||||
|
||||
An entity class must not be final nor read-only, although
|
||||
it can contain final methods or read-only properties.
|
||||
An entity class can be final or read-only when you use
|
||||
:ref:`native lazy objects <reference-native-lazy-objects>`.
|
||||
It may contain final methods or read-only properties too.
|
||||
|
||||
An Example Model: Bug Tracker
|
||||
-----------------------------
|
||||
@@ -534,7 +535,7 @@ the ``id`` tag. It has a ``generator`` tag nested inside, which
|
||||
specifies that the primary key generation mechanism should automatically
|
||||
use the database platform's native id generation strategy (for
|
||||
example, AUTO INCREMENT in the case of MySql, or Sequences in the
|
||||
case of PostgreSql and Oracle).
|
||||
case of PostgreSQL and Oracle).
|
||||
|
||||
Now that we have defined our first entity and its metadata,
|
||||
let's update the database schema:
|
||||
@@ -1287,7 +1288,7 @@ The console output of this script is then:
|
||||
result set to retrieve entities from the database. DQL boils down to a
|
||||
Native SQL statement and a ``ResultSetMapping`` instance itself. Using
|
||||
Native SQL you could even use stored procedures for data retrieval, or
|
||||
make use of advanced non-portable database queries like PostgreSql's
|
||||
make use of advanced non-portable database queries like PostgreSQL's
|
||||
recursive queries.
|
||||
|
||||
|
||||
|
||||
@@ -2023,14 +2023,8 @@ parameters:
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$relationToTargetKeyColumns\.$#'
|
||||
identifier: property.notFound
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$sourceToTargetKeyColumns\.$#'
|
||||
identifier: property.notFound
|
||||
message: '#^Access to property \$value on an unknown class Doctrine\\ORM\\Persisters\\Entity\\BackedEnum\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
@@ -2040,24 +2034,18 @@ parameters:
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Class Doctrine\\ORM\\Persisters\\Entity\\BackedEnum not found\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:__construct\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
|
||||
identifier: missingType.generics
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:expandCriteriaParameters\(\) should return array\{list\<mixed\>, list\<Doctrine\\DBAL\\ArrayParameterType\:\:ASCII\|Doctrine\\DBAL\\ArrayParameterType\:\:BINARY\|Doctrine\\DBAL\\ArrayParameterType\:\:INTEGER\|Doctrine\\DBAL\\ArrayParameterType\:\:STRING\|Doctrine\\DBAL\\ParameterType\:\:ASCII\|Doctrine\\DBAL\\ParameterType\:\:BINARY\|Doctrine\\DBAL\\ParameterType\:\:BOOLEAN\|Doctrine\\DBAL\\ParameterType\:\:INTEGER\|Doctrine\\DBAL\\ParameterType\:\:LARGE_OBJECT\|Doctrine\\DBAL\\ParameterType\:\:NULL\|Doctrine\\DBAL\\ParameterType\:\:STRING\|string\>\} but returns array\{array\<mixed\>, list\<Doctrine\\DBAL\\ArrayParameterType\:\:ASCII\|Doctrine\\DBAL\\ArrayParameterType\:\:BINARY\|Doctrine\\DBAL\\ArrayParameterType\:\:INTEGER\|Doctrine\\DBAL\\ArrayParameterType\:\:STRING\|Doctrine\\DBAL\\ParameterType\:\:ASCII\|Doctrine\\DBAL\\ParameterType\:\:BINARY\|Doctrine\\DBAL\\ParameterType\:\:BOOLEAN\|Doctrine\\DBAL\\ParameterType\:\:INTEGER\|Doctrine\\DBAL\\ParameterType\:\:LARGE_OBJECT\|Doctrine\\DBAL\\ParameterType\:\:NULL\|Doctrine\\DBAL\\ParameterType\:\:STRING\|string\>\}\.$#'
|
||||
identifier: return.type
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:expandParameters\(\) should return array\{list\<mixed\>, list\<Doctrine\\DBAL\\ArrayParameterType\:\:ASCII\|Doctrine\\DBAL\\ArrayParameterType\:\:BINARY\|Doctrine\\DBAL\\ArrayParameterType\:\:INTEGER\|Doctrine\\DBAL\\ArrayParameterType\:\:STRING\|Doctrine\\DBAL\\ParameterType\:\:ASCII\|Doctrine\\DBAL\\ParameterType\:\:BINARY\|Doctrine\\DBAL\\ParameterType\:\:BOOLEAN\|Doctrine\\DBAL\\ParameterType\:\:INTEGER\|Doctrine\\DBAL\\ParameterType\:\:LARGE_OBJECT\|Doctrine\\DBAL\\ParameterType\:\:NULL\|Doctrine\\DBAL\\ParameterType\:\:STRING\|string\>\} but returns array\{array\<mixed\>, list\<Doctrine\\DBAL\\ArrayParameterType\:\:ASCII\|Doctrine\\DBAL\\ArrayParameterType\:\:BINARY\|Doctrine\\DBAL\\ArrayParameterType\:\:INTEGER\|Doctrine\\DBAL\\ArrayParameterType\:\:STRING\|Doctrine\\DBAL\\ParameterType\:\:ASCII\|Doctrine\\DBAL\\ParameterType\:\:BINARY\|Doctrine\\DBAL\\ParameterType\:\:BOOLEAN\|Doctrine\\DBAL\\ParameterType\:\:INTEGER\|Doctrine\\DBAL\\ParameterType\:\:LARGE_OBJECT\|Doctrine\\DBAL\\ParameterType\:\:NULL\|Doctrine\\DBAL\\ParameterType\:\:STRING\|string\>\}\.$#'
|
||||
identifier: return.type
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:expandToManyParameters\(\) return type has no value type specified in iterable type array\.$#'
|
||||
identifier: missingType.iterableValue
|
||||
@@ -2094,12 +2082,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:getIndividualValue\(\) should return list\<mixed\> but returns array\<mixed\>\.$#'
|
||||
identifier: return.type
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:getSelectColumnAssociationSQL\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
|
||||
identifier: missingType.generics
|
||||
@@ -2112,18 +2094,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:getTypes\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
|
||||
identifier: missingType.generics
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:getTypes\(\) should return list\<Doctrine\\DBAL\\ArrayParameterType\:\:ASCII\|Doctrine\\DBAL\\ArrayParameterType\:\:BINARY\|Doctrine\\DBAL\\ArrayParameterType\:\:INTEGER\|Doctrine\\DBAL\\ArrayParameterType\:\:STRING\|Doctrine\\DBAL\\ParameterType\:\:ASCII\|Doctrine\\DBAL\\ParameterType\:\:BINARY\|Doctrine\\DBAL\\ParameterType\:\:BOOLEAN\|Doctrine\\DBAL\\ParameterType\:\:INTEGER\|Doctrine\\DBAL\\ParameterType\:\:LARGE_OBJECT\|Doctrine\\DBAL\\ParameterType\:\:NULL\|Doctrine\\DBAL\\ParameterType\:\:STRING\|string\> but returns list\<Doctrine\\DBAL\\ArrayParameterType\:\:ASCII\|Doctrine\\DBAL\\ArrayParameterType\:\:BINARY\|Doctrine\\DBAL\\ArrayParameterType\:\:INTEGER\|Doctrine\\DBAL\\ArrayParameterType\:\:STRING\|int\>\.$#'
|
||||
identifier: return.type
|
||||
count: 1
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:loadCollectionFromStatement\(\) has parameter \$coll with generic class Doctrine\\ORM\\PersistentCollection but does not specify its types\: TKey, T$#'
|
||||
identifier: missingType.generics
|
||||
@@ -3603,6 +3573,18 @@ parameters:
|
||||
count: 1
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
-
|
||||
message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$relationToTargetKeyColumns\.$#'
|
||||
identifier: property.notFound
|
||||
count: 1
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
-
|
||||
message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$sourceToTargetKeyColumns\.$#'
|
||||
identifier: property.notFound
|
||||
count: 1
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Utility\\PersisterHelper\:\:getTypeOfColumn\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
|
||||
identifier: missingType.generics
|
||||
@@ -3614,3 +3596,15 @@ parameters:
|
||||
identifier: missingType.generics
|
||||
count: 1
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Utility\\PersisterHelper\:\:inferParameterTypes\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
|
||||
identifier: missingType.generics
|
||||
count: 1
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Utility\\PersisterHelper\:\:inferParameterTypes\(\) should return list\<Doctrine\\DBAL\\ArrayParameterType\:\:ASCII\|Doctrine\\DBAL\\ArrayParameterType\:\:BINARY\|Doctrine\\DBAL\\ArrayParameterType\:\:INTEGER\|Doctrine\\DBAL\\ArrayParameterType\:\:STRING\|Doctrine\\DBAL\\ParameterType\:\:ASCII\|Doctrine\\DBAL\\ParameterType\:\:BINARY\|Doctrine\\DBAL\\ParameterType\:\:BOOLEAN\|Doctrine\\DBAL\\ParameterType\:\:INTEGER\|Doctrine\\DBAL\\ParameterType\:\:LARGE_OBJECT\|Doctrine\\DBAL\\ParameterType\:\:NULL\|Doctrine\\DBAL\\ParameterType\:\:STRING\|string\> but returns list\<Doctrine\\DBAL\\ArrayParameterType\:\:ASCII\|Doctrine\\DBAL\\ArrayParameterType\:\:BINARY\|Doctrine\\DBAL\\ArrayParameterType\:\:INTEGER\|Doctrine\\DBAL\\ArrayParameterType\:\:STRING\|int\>\.$#'
|
||||
identifier: return.type
|
||||
count: 1
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
@@ -11,7 +11,7 @@ parameters:
|
||||
# We can be certain that those values are not matched.
|
||||
-
|
||||
message: '~^Match expression does not handle remaining values:~'
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
# DBAL 4 compatibility
|
||||
-
|
||||
@@ -109,12 +109,12 @@ parameters:
|
||||
path: src/Mapping/Driver/AttributeDriver.php
|
||||
|
||||
-
|
||||
message: '~^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:getArrayBindingType\(\) never returns .* so it can be removed from the return type\.$~'
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
message: '~^Method Doctrine\\ORM\\Utility\\PersisterHelper\:\:getArrayBindingType\(\) never returns .* so it can be removed from the return type\.$~'
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
-
|
||||
message: '~getTypes.*should return~'
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
message: '~inferParameterTypes.*should return~'
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
-
|
||||
message: '~.*appendLockHint.*expects.*LockMode given~'
|
||||
|
||||
@@ -10,15 +10,15 @@ parameters:
|
||||
# We can be certain that those values are not matched.
|
||||
-
|
||||
message: '~^Match expression does not handle remaining values:~'
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
# DBAL 4 compatibility
|
||||
-
|
||||
message: '~^Method Doctrine\\ORM\\Query\\AST\\Functions\\TrimFunction::getTrimMode\(\) never returns .* so it can be removed from the return type\.$~'
|
||||
path: src/Query/AST/Functions/TrimFunction.php
|
||||
-
|
||||
message: '~^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:getArrayBindingType\(\) never returns .* so it can be removed from the return type\.$~'
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
message: '~^Method Doctrine\\ORM\\Utility\\PersisterHelper\:\:getArrayBindingType\(\) never returns .* so it can be removed from the return type\.$~'
|
||||
path: src/Utility/PersisterHelper.php
|
||||
|
||||
# Compatibility with DBAL 3
|
||||
# See https://github.com/doctrine/dbal/pull/3480
|
||||
|
||||
@@ -248,9 +248,16 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
if ($value === null && ($operator === Comparison::EQ || $operator === Comparison::NEQ)) {
|
||||
$whereClauses[] = sprintf('te.%s %s NULL', $field, $operator === Comparison::EQ ? 'IS' : 'IS NOT');
|
||||
} else {
|
||||
$whereClauses[] = sprintf('te.%s %s ?', $field, $operator);
|
||||
$params[] = $value;
|
||||
$paramTypes[] = PersisterHelper::getTypeOfField($name, $targetClass, $this->em)[0];
|
||||
if ($operator === Comparison::IN) {
|
||||
$whereClauses[] = sprintf('te.%s IN (?)', $field);
|
||||
} elseif ($operator === Comparison::NIN) {
|
||||
$whereClauses[] = sprintf('te.%s NOT IN (?)', $field);
|
||||
} else {
|
||||
$whereClauses[] = sprintf('te.%s %s ?', $field, $operator);
|
||||
}
|
||||
|
||||
$params = [...$params, ...PersisterHelper::convertToParameterValue($value, $this->em)];
|
||||
$paramTypes = [...$paramTypes, ...PersisterHelper::inferParameterTypes($name, $value, $targetClass, $this->em)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Persisters\Entity;
|
||||
|
||||
use BackedEnum;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\Common\Collections\Expr\Comparison;
|
||||
use Doctrine\Common\Collections\Order;
|
||||
@@ -31,9 +30,7 @@ use Doctrine\ORM\Persisters\Exception\InvalidOrientation;
|
||||
use Doctrine\ORM\Persisters\Exception\UnrecognizedField;
|
||||
use Doctrine\ORM\Persisters\SqlExpressionVisitor;
|
||||
use Doctrine\ORM\Persisters\SqlValueVisitor;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\Query\QueryException;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\ORM\Repository\Exception\InvalidFindByCall;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
@@ -45,7 +42,6 @@ use LengthException;
|
||||
use function array_combine;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function array_search;
|
||||
use function array_unique;
|
||||
use function array_values;
|
||||
@@ -53,7 +49,6 @@ use function assert;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function reset;
|
||||
use function spl_object_id;
|
||||
use function sprintf;
|
||||
@@ -353,7 +348,7 @@ class BasicEntityPersister implements EntityPersister
|
||||
$types = [];
|
||||
|
||||
foreach ($id as $field => $value) {
|
||||
$types = [...$types, ...$this->getTypes($field, $value, $versionedClass)];
|
||||
$types = [...$types, ...PersisterHelper::inferParameterTypes($field, $value, $versionedClass, $this->em)];
|
||||
}
|
||||
|
||||
return $types;
|
||||
@@ -919,8 +914,8 @@ class BasicEntityPersister implements EntityPersister
|
||||
continue;
|
||||
}
|
||||
|
||||
$sqlParams = [...$sqlParams, ...$this->getValues($value)];
|
||||
$sqlTypes = [...$sqlTypes, ...$this->getTypes($field, $value, $this->class)];
|
||||
$sqlParams = [...$sqlParams, ...PersisterHelper::convertToParameterValue($value, $this->em)];
|
||||
$sqlTypes = [...$sqlTypes, ...PersisterHelper::inferParameterTypes($field, $value, $this->class, $this->em)];
|
||||
}
|
||||
|
||||
return [$sqlParams, $sqlTypes];
|
||||
@@ -1858,8 +1853,8 @@ class BasicEntityPersister implements EntityPersister
|
||||
continue; // skip null values.
|
||||
}
|
||||
|
||||
$types = [...$types, ...$this->getTypes($field, $value, $this->class)];
|
||||
$params = array_merge($params, $this->getValues($value));
|
||||
$types = [...$types, ...PersisterHelper::inferParameterTypes($field, $value, $this->class, $this->em)];
|
||||
$params = [...$params, ...PersisterHelper::convertToParameterValue($value, $this->em)];
|
||||
}
|
||||
|
||||
return [$params, $types];
|
||||
@@ -1887,130 +1882,13 @@ class BasicEntityPersister implements EntityPersister
|
||||
continue; // skip null values.
|
||||
}
|
||||
|
||||
$types = [...$types, ...$this->getTypes($criterion['field'], $criterion['value'], $criterion['class'])];
|
||||
$params = array_merge($params, $this->getValues($criterion['value']));
|
||||
$types = [...$types, ...PersisterHelper::inferParameterTypes($criterion['field'], $criterion['value'], $criterion['class'], $this->em)];
|
||||
$params = [...$params, ...PersisterHelper::convertToParameterValue($criterion['value'], $this->em)];
|
||||
}
|
||||
|
||||
return [$params, $types];
|
||||
}
|
||||
|
||||
/**
|
||||
* Infers field types to be used by parameter type casting.
|
||||
*
|
||||
* @return list<ParameterType|ArrayParameterType|int|string>
|
||||
* @phpstan-return list<ParameterType::*|ArrayParameterType::*|string>
|
||||
*
|
||||
* @throws QueryException
|
||||
*/
|
||||
private function getTypes(string $field, mixed $value, ClassMetadata $class): array
|
||||
{
|
||||
$types = [];
|
||||
|
||||
switch (true) {
|
||||
case isset($class->fieldMappings[$field]):
|
||||
$types = array_merge($types, [$class->fieldMappings[$field]->type]);
|
||||
break;
|
||||
|
||||
case isset($class->associationMappings[$field]):
|
||||
$assoc = $this->em->getMetadataFactory()->getOwningSide($class->associationMappings[$field]);
|
||||
$class = $this->em->getClassMetadata($assoc->targetEntity);
|
||||
|
||||
if ($assoc->isManyToManyOwningSide()) {
|
||||
$columns = $assoc->relationToTargetKeyColumns;
|
||||
} else {
|
||||
assert($assoc->isToOneOwningSide());
|
||||
$columns = $assoc->sourceToTargetKeyColumns;
|
||||
}
|
||||
|
||||
foreach ($columns as $column) {
|
||||
$types[] = PersisterHelper::getTypeOfColumn($column, $class, $this->em);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$types[] = ParameterType::STRING;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
return array_map($this->getArrayBindingType(...), $types);
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
/** @phpstan-return ArrayParameterType::* */
|
||||
private function getArrayBindingType(ParameterType|int|string $type): ArrayParameterType|int
|
||||
{
|
||||
if (! $type instanceof ParameterType) {
|
||||
$type = Type::getType((string) $type)->getBindingType();
|
||||
}
|
||||
|
||||
return match ($type) {
|
||||
ParameterType::STRING => ArrayParameterType::STRING,
|
||||
ParameterType::INTEGER => ArrayParameterType::INTEGER,
|
||||
ParameterType::ASCII => ArrayParameterType::ASCII,
|
||||
ParameterType::BINARY => ArrayParameterType::BINARY,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the parameters that identifies a value.
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function getValues(mixed $value): array
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$newValue = [];
|
||||
|
||||
foreach ($value as $itemValue) {
|
||||
$newValue = array_merge($newValue, $this->getValues($itemValue));
|
||||
}
|
||||
|
||||
return [$newValue];
|
||||
}
|
||||
|
||||
return $this->getIndividualValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an individual parameter value.
|
||||
*
|
||||
* @phpstan-return list<mixed>
|
||||
*/
|
||||
private function getIndividualValue(mixed $value): array
|
||||
{
|
||||
if (! is_object($value)) {
|
||||
return [$value];
|
||||
}
|
||||
|
||||
if ($value instanceof BackedEnum) {
|
||||
return [$value->value];
|
||||
}
|
||||
|
||||
$valueClass = DefaultProxyClassNameResolver::getClass($value);
|
||||
|
||||
if ($this->em->getMetadataFactory()->isTransient($valueClass)) {
|
||||
return [$value];
|
||||
}
|
||||
|
||||
$class = $this->em->getClassMetadata($valueClass);
|
||||
|
||||
if ($class->isIdentifierComposite) {
|
||||
$newValue = [];
|
||||
|
||||
foreach ($class->getIdentifierValues($value) as $innerValue) {
|
||||
$newValue = array_merge($newValue, $this->getValues($innerValue));
|
||||
}
|
||||
|
||||
return $newValue;
|
||||
}
|
||||
|
||||
return [$this->em->getUnitOfWork()->getSingleIdentifierValue($value)];
|
||||
}
|
||||
|
||||
public function exists(object $entity, Criteria|null $extraConditions = null): bool
|
||||
{
|
||||
$criteria = $this->class->getIdentifierValues($entity);
|
||||
|
||||
@@ -61,7 +61,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
*/
|
||||
private function getVersionedClassMetadata(): ClassMetadata
|
||||
{
|
||||
if (isset($this->class->fieldMappings[$this->class->versionField]->inherited)) {
|
||||
if ($this->class->versionField !== null && isset($this->class->fieldMappings[$this->class->versionField]->inherited)) {
|
||||
$definingClassName = $this->class->fieldMappings[$this->class->versionField]->inherited;
|
||||
|
||||
return $this->em->getClassMetadata($definingClassName);
|
||||
|
||||
@@ -1412,7 +1412,9 @@ class SqlWalker
|
||||
|
||||
$sqlParts[] = $col . ' AS ' . $columnAlias;
|
||||
|
||||
$this->scalarResultAliasMap[$resultAlias][] = $columnAlias;
|
||||
if ($resultAlias !== null) {
|
||||
$this->scalarResultAliasMap[$resultAlias][] = $columnAlias;
|
||||
}
|
||||
|
||||
$this->rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name);
|
||||
|
||||
@@ -1445,7 +1447,9 @@ class SqlWalker
|
||||
|
||||
$sqlParts[] = $col . ' AS ' . $columnAlias;
|
||||
|
||||
$this->scalarResultAliasMap[$resultAlias][] = $columnAlias;
|
||||
if ($resultAlias !== null) {
|
||||
$this->scalarResultAliasMap[$resultAlias][] = $columnAlias;
|
||||
}
|
||||
|
||||
$this->rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName);
|
||||
}
|
||||
|
||||
@@ -132,7 +132,9 @@ class LimitSubqueryOutputWalker extends SqlOutputWalker
|
||||
$selectAliasToExpressionMap = [];
|
||||
// Get any aliases that are available for select expressions.
|
||||
foreach ($AST->selectClause->selectExpressions as $selectExpression) {
|
||||
$selectAliasToExpressionMap[$selectExpression->fieldIdentificationVariable] = $selectExpression->expression;
|
||||
if ($selectExpression->fieldIdentificationVariable !== null) {
|
||||
$selectAliasToExpressionMap[$selectExpression->fieldIdentificationVariable] = $selectExpression->expression;
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild string orderby expressions to use the select expression they're referencing
|
||||
|
||||
@@ -4,11 +4,21 @@ declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Utility;
|
||||
|
||||
use BackedEnum;
|
||||
use Doctrine\DBAL\ArrayParameterType;
|
||||
use Doctrine\DBAL\ParameterType;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\ORM\Query\QueryException;
|
||||
use RuntimeException;
|
||||
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function assert;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
@@ -105,4 +115,121 @@ class PersisterHelper
|
||||
$class->getName(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Infers field types to be used by parameter type casting.
|
||||
*
|
||||
* @return list<ParameterType|int|string>
|
||||
* @phpstan-return list<ParameterType::*|ArrayParameterType::*|string>
|
||||
*
|
||||
* @throws QueryException
|
||||
*/
|
||||
public static function inferParameterTypes(
|
||||
string $field,
|
||||
mixed $value,
|
||||
ClassMetadata $class,
|
||||
EntityManagerInterface $em,
|
||||
): array {
|
||||
$types = [];
|
||||
|
||||
switch (true) {
|
||||
case isset($class->fieldMappings[$field]):
|
||||
$types = array_merge($types, [$class->fieldMappings[$field]->type]);
|
||||
break;
|
||||
|
||||
case isset($class->associationMappings[$field]):
|
||||
$assoc = $em->getMetadataFactory()->getOwningSide($class->associationMappings[$field]);
|
||||
$class = $em->getClassMetadata($assoc->targetEntity);
|
||||
|
||||
if ($assoc->isManyToManyOwningSide()) {
|
||||
$columns = $assoc->relationToTargetKeyColumns;
|
||||
} else {
|
||||
assert($assoc->isToOneOwningSide());
|
||||
$columns = $assoc->sourceToTargetKeyColumns;
|
||||
}
|
||||
|
||||
foreach ($columns as $column) {
|
||||
$types[] = self::getTypeOfColumn($column, $class, $em);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$types[] = ParameterType::STRING;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
return array_map(self::getArrayBindingType(...), $types);
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
/** @phpstan-return ArrayParameterType::* */
|
||||
private static function getArrayBindingType(ParameterType|int|string $type): ArrayParameterType|int
|
||||
{
|
||||
if (! $type instanceof ParameterType) {
|
||||
$type = Type::getType((string) $type)->getBindingType();
|
||||
}
|
||||
|
||||
return match ($type) {
|
||||
ParameterType::STRING => ArrayParameterType::STRING,
|
||||
ParameterType::INTEGER => ArrayParameterType::INTEGER,
|
||||
ParameterType::ASCII => ArrayParameterType::ASCII,
|
||||
ParameterType::BINARY => ArrayParameterType::BINARY,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to the type and value required to bind it as a parameter.
|
||||
*
|
||||
* @return list<mixed>
|
||||
*/
|
||||
public static function convertToParameterValue(mixed $value, EntityManagerInterface $em): array
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$newValue = [];
|
||||
|
||||
foreach ($value as $itemValue) {
|
||||
$newValue = array_merge($newValue, self::convertToParameterValue($itemValue, $em));
|
||||
}
|
||||
|
||||
return [$newValue];
|
||||
}
|
||||
|
||||
return self::convertIndividualValue($value, $em);
|
||||
}
|
||||
|
||||
/** @phpstan-return list<mixed> */
|
||||
private static function convertIndividualValue(mixed $value, EntityManagerInterface $em): array
|
||||
{
|
||||
if (! is_object($value)) {
|
||||
return [$value];
|
||||
}
|
||||
|
||||
if ($value instanceof BackedEnum) {
|
||||
return [$value->value];
|
||||
}
|
||||
|
||||
$valueClass = DefaultProxyClassNameResolver::getClass($value);
|
||||
|
||||
if ($em->getMetadataFactory()->isTransient($valueClass)) {
|
||||
return [$value];
|
||||
}
|
||||
|
||||
$class = $em->getClassMetadata($valueClass);
|
||||
|
||||
if ($class->isIdentifierComposite) {
|
||||
$newValue = [];
|
||||
|
||||
foreach ($class->getIdentifierValues($value) as $innerValue) {
|
||||
$newValue = array_merge($newValue, self::convertToParameterValue($innerValue, $em));
|
||||
}
|
||||
|
||||
return $newValue;
|
||||
}
|
||||
|
||||
return [$em->getUnitOfWork()->getSingleIdentifierValue($value)];
|
||||
}
|
||||
}
|
||||
|
||||
30
tests/Tests/Models/Enums/BookCategory.php
Normal file
30
tests/Tests/Models/Enums/BookCategory.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\Models\Enums;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping\Column;
|
||||
use Doctrine\ORM\Mapping\Entity;
|
||||
use Doctrine\ORM\Mapping\GeneratedValue;
|
||||
use Doctrine\ORM\Mapping\Id;
|
||||
use Doctrine\ORM\Mapping\ManyToMany;
|
||||
|
||||
#[Entity]
|
||||
class BookCategory
|
||||
{
|
||||
#[Id]
|
||||
#[Column]
|
||||
#[GeneratedValue]
|
||||
public int $id;
|
||||
|
||||
#[ManyToMany(targetEntity: BookWithGenre::class, mappedBy: 'categories')]
|
||||
public Collection $books;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->books = new ArrayCollection();
|
||||
}
|
||||
}
|
||||
11
tests/Tests/Models/Enums/BookGenre.php
Normal file
11
tests/Tests/Models/Enums/BookGenre.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\Models\Enums;
|
||||
|
||||
enum BookGenre: string
|
||||
{
|
||||
case FICTION = 'fiction';
|
||||
case NON_FICTION = 'non fiction';
|
||||
}
|
||||
38
tests/Tests/Models/Enums/BookWithGenre.php
Normal file
38
tests/Tests/Models/Enums/BookWithGenre.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\Models\Enums;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping\Column;
|
||||
use Doctrine\ORM\Mapping\Entity;
|
||||
use Doctrine\ORM\Mapping\GeneratedValue;
|
||||
use Doctrine\ORM\Mapping\Id;
|
||||
use Doctrine\ORM\Mapping\ManyToMany;
|
||||
use Doctrine\ORM\Mapping\ManyToOne;
|
||||
|
||||
#[Entity]
|
||||
class BookWithGenre
|
||||
{
|
||||
#[Id]
|
||||
#[GeneratedValue]
|
||||
#[Column]
|
||||
public int $id;
|
||||
|
||||
#[ManyToOne(targetEntity: Library::class, inversedBy: 'books')]
|
||||
public Library $library;
|
||||
|
||||
#[Column(enumType: BookGenre::class)]
|
||||
public BookGenre $genre;
|
||||
|
||||
#[ManyToMany(targetEntity: BookCategory::class, inversedBy: 'books')]
|
||||
public Collection $categories;
|
||||
|
||||
public function __construct(BookGenre $genre)
|
||||
{
|
||||
$this->genre = $genre;
|
||||
$this->categories = new ArrayCollection();
|
||||
}
|
||||
}
|
||||
30
tests/Tests/Models/Enums/Library.php
Normal file
30
tests/Tests/Models/Enums/Library.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\Models\Enums;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping\Column;
|
||||
use Doctrine\ORM\Mapping\Entity;
|
||||
use Doctrine\ORM\Mapping\GeneratedValue;
|
||||
use Doctrine\ORM\Mapping\Id;
|
||||
use Doctrine\ORM\Mapping\OneToMany;
|
||||
|
||||
#[Entity]
|
||||
class Library
|
||||
{
|
||||
#[Id]
|
||||
#[GeneratedValue]
|
||||
#[Column]
|
||||
public int $id;
|
||||
|
||||
#[OneToMany(targetEntity: BookWithGenre::class, mappedBy: 'library')]
|
||||
public Collection $books;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->books = new ArrayCollection();
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,8 @@ use Doctrine\ORM\Proxy\ProxyFactory;
|
||||
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
|
||||
use Doctrine\Tests\Models\DDC753\DDC753CustomRepository;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhp;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
|
||||
@@ -39,7 +39,7 @@ class ConfigurationTest extends TestCase
|
||||
$this->configuration = new Configuration();
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testSetGetProxyDir(): void
|
||||
{
|
||||
self::assertNull($this->configuration->getProxyDir()); // defaults
|
||||
@@ -48,7 +48,7 @@ class ConfigurationTest extends TestCase
|
||||
self::assertSame(__DIR__, $this->configuration->getProxyDir());
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testSetGetAutoGenerateProxyClasses(): void
|
||||
{
|
||||
self::assertSame(ProxyFactory::AUTOGENERATE_ALWAYS, $this->configuration->getAutoGenerateProxyClasses()); // defaults
|
||||
@@ -63,7 +63,7 @@ class ConfigurationTest extends TestCase
|
||||
self::assertSame(ProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS, $this->configuration->getAutoGenerateProxyClasses());
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testSetGetProxyNamespace(): void
|
||||
{
|
||||
self::assertNull($this->configuration->getProxyNamespace()); // defaults
|
||||
@@ -222,7 +222,7 @@ class ConfigurationTest extends TestCase
|
||||
}
|
||||
|
||||
#[RequiresPhp('8.4')]
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testDisablingNativeLazyObjectsIsDeprecated(): void
|
||||
{
|
||||
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/pull/12005');
|
||||
|
||||
@@ -7,10 +7,11 @@ namespace Doctrine\Tests\ORM\Functional;
|
||||
use Doctrine\Tests\Models\EagerFetchedCompositeOneToMany\RootEntity;
|
||||
use Doctrine\Tests\Models\EagerFetchedCompositeOneToMany\SecondLevel;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
final class EagerFetchOneToManyWithCompositeKeyTest extends OrmFunctionalTestCase
|
||||
{
|
||||
/** @ticket 11154 */
|
||||
#[Group('GH11154')]
|
||||
public function testItDoesNotThrowAnExceptionWhenTriggeringALoad(): void
|
||||
{
|
||||
$this->setUpEntitySchema([RootEntity::class, SecondLevel::class]);
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\Common\Collections\Expr\Comparison;
|
||||
use Doctrine\DBAL\Types\EnumType;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
use Doctrine\ORM\Mapping\Column;
|
||||
@@ -13,10 +15,14 @@ use Doctrine\ORM\Tools\SchemaTool;
|
||||
use Doctrine\Tests\Mocks\AttributeDriverFactory;
|
||||
use Doctrine\Tests\Models\DataTransferObjects\DtoWithArrayOfEnums;
|
||||
use Doctrine\Tests\Models\DataTransferObjects\DtoWithEnum;
|
||||
use Doctrine\Tests\Models\Enums\BookCategory;
|
||||
use Doctrine\Tests\Models\Enums\BookGenre;
|
||||
use Doctrine\Tests\Models\Enums\BookWithGenre;
|
||||
use Doctrine\Tests\Models\Enums\Card;
|
||||
use Doctrine\Tests\Models\Enums\CardNativeEnum;
|
||||
use Doctrine\Tests\Models\Enums\CardWithDefault;
|
||||
use Doctrine\Tests\Models\Enums\CardWithNullable;
|
||||
use Doctrine\Tests\Models\Enums\Library;
|
||||
use Doctrine\Tests\Models\Enums\Product;
|
||||
use Doctrine\Tests\Models\Enums\Quantity;
|
||||
use Doctrine\Tests\Models\Enums\Scale;
|
||||
@@ -25,6 +31,7 @@ use Doctrine\Tests\Models\Enums\TypedCard;
|
||||
use Doctrine\Tests\Models\Enums\TypedCardNativeEnum;
|
||||
use Doctrine\Tests\Models\Enums\Unit;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use Generator;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
|
||||
use function class_exists;
|
||||
@@ -528,4 +535,68 @@ EXCEPTION
|
||||
|
||||
self::assertSame(Suit::Hearts, $card->suit);
|
||||
}
|
||||
|
||||
#[DataProvider('provideGenreMatchingExpressions')]
|
||||
public function testEnumCollectionMatchingOnOneToMany(Comparison $comparison): void
|
||||
{
|
||||
$this->setUpEntitySchema([BookWithGenre::class, Library::class, BookCategory::class]);
|
||||
|
||||
$library = new Library();
|
||||
|
||||
$fictionBook = new BookWithGenre(BookGenre::FICTION);
|
||||
$fictionBook->library = $library;
|
||||
|
||||
$nonfictionBook = new BookWithGenre(BookGenre::NON_FICTION);
|
||||
$nonfictionBook->library = $library;
|
||||
|
||||
$this->_em->persist($library);
|
||||
$this->_em->persist($nonfictionBook);
|
||||
$this->_em->persist($fictionBook);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$library = $this->_em->find(Library::class, $library->id);
|
||||
self::assertFalse($library->books->isInitialized(), 'Pre-condition: lazy collection');
|
||||
|
||||
$result = $library->books->matching(Criteria::create()->where($comparison));
|
||||
|
||||
self::assertCount(1, $result);
|
||||
self::assertSame($nonfictionBook->id, $result[0]->id);
|
||||
}
|
||||
|
||||
#[DataProvider('provideGenreMatchingExpressions')]
|
||||
public function testEnumCollectionMatchingOnManyToMany(Comparison $comparison): void
|
||||
{
|
||||
$this->setUpEntitySchema([Library::class, BookWithGenre::class, BookCategory::class]);
|
||||
|
||||
$category = new BookCategory();
|
||||
|
||||
$fictionBook = new BookWithGenre(BookGenre::FICTION);
|
||||
$fictionBook->categories->add($category);
|
||||
|
||||
$nonfictionBook = new BookWithGenre(BookGenre::NON_FICTION);
|
||||
$nonfictionBook->categories->add($category);
|
||||
|
||||
$this->_em->persist($category);
|
||||
$this->_em->persist($nonfictionBook);
|
||||
$this->_em->persist($fictionBook);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$category = $this->_em->find(BookCategory::class, $category->id);
|
||||
self::assertFalse($category->books->isInitialized(), 'Pre-condition: lazy collection');
|
||||
|
||||
$result = $category->books->matching(Criteria::create()->where($comparison));
|
||||
|
||||
self::assertCount(1, $result);
|
||||
self::assertSame($nonfictionBook->id, $result[0]->id);
|
||||
}
|
||||
|
||||
public static function provideGenreMatchingExpressions(): Generator
|
||||
{
|
||||
yield [Criteria::expr()->eq('genre', BookGenre::NON_FICTION)];
|
||||
yield [Criteria::expr()->in('genre', [BookGenre::NON_FICTION])];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function assert;
|
||||
use function class_exists;
|
||||
use function get_class;
|
||||
|
||||
/**
|
||||
* Basic many-to-many association tests.
|
||||
@@ -573,6 +574,44 @@ class ManyToManyBasicAssociationTest extends OrmFunctionalTestCase
|
||||
self::assertFalse($user->groups->isInitialized(), 'Post-condition: matching does not initialize collection');
|
||||
}
|
||||
|
||||
public function testMatchingWithInCondition(): void
|
||||
{
|
||||
$user = $this->addCmsUserGblancoWithGroups(2);
|
||||
$this->_em->clear();
|
||||
|
||||
$user = $this->_em->find(get_class($user), $user->id);
|
||||
|
||||
$groups = $user->groups;
|
||||
self::assertFalse($user->groups->isInitialized(), 'Pre-condition: lazy collection');
|
||||
|
||||
$criteria = Criteria::create()->where(Criteria::expr()->in('name', ['Developers_1']));
|
||||
$result = $groups->matching($criteria);
|
||||
|
||||
self::assertCount(1, $result);
|
||||
self::assertEquals('Developers_1', $result[0]->name);
|
||||
|
||||
self::assertFalse($user->groups->isInitialized(), 'Post-condition: matching does not initialize collection');
|
||||
}
|
||||
|
||||
public function testMatchingWithNotInCondition(): void
|
||||
{
|
||||
$user = $this->addCmsUserGblancoWithGroups(2);
|
||||
$this->_em->clear();
|
||||
|
||||
$user = $this->_em->find(get_class($user), $user->id);
|
||||
|
||||
$groups = $user->groups;
|
||||
self::assertFalse($user->groups->isInitialized(), 'Pre-condition: lazy collection');
|
||||
|
||||
$criteria = Criteria::create()->where(Criteria::expr()->notIn('name', ['Developers_0']));
|
||||
$result = $groups->matching($criteria);
|
||||
|
||||
self::assertCount(1, $result);
|
||||
self::assertEquals('Developers_1', $result[0]->name);
|
||||
|
||||
self::assertFalse($user->groups->isInitialized(), 'Post-condition: matching does not initialize collection');
|
||||
}
|
||||
|
||||
private function removeTransactionCommandsFromQueryLog(): void
|
||||
{
|
||||
$log = $this->getQueryLog();
|
||||
|
||||
@@ -14,7 +14,7 @@ use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use Generator;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
|
||||
use ReflectionMethod;
|
||||
use Symfony\Component\VarExporter\Instantiator;
|
||||
use Symfony\Component\VarExporter\VarExporter;
|
||||
@@ -35,7 +35,7 @@ class ParserResultSerializationTest extends OrmFunctionalTestCase
|
||||
|
||||
/** @param Closure(ParserResult): ParserResult $toSerializedAndBack */
|
||||
#[DataProvider('provideToSerializedAndBack')]
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testSerializeParserResultForQueryWithSqlWalker(Closure $toSerializedAndBack): void
|
||||
{
|
||||
$query = $this->_em
|
||||
@@ -131,7 +131,6 @@ class ParserResultSerializationTest extends OrmFunctionalTestCase
|
||||
private static function parseQuery(Query $query): ParserResult
|
||||
{
|
||||
$r = new ReflectionMethod($query, 'parse');
|
||||
$r->setAccessible(true);
|
||||
|
||||
return $r->invoke($query);
|
||||
}
|
||||
|
||||
@@ -122,8 +122,7 @@ class QueryCacheTest extends OrmFunctionalTestCase
|
||||
|
||||
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||
|
||||
$sqlExecMock = $this->getMockBuilder(AbstractSqlExecutor::class)
|
||||
->getMockForAbstractClass();
|
||||
$sqlExecMock = $this->createMock(AbstractSqlExecutor::class);
|
||||
|
||||
$sqlExecMock->expects(self::once())
|
||||
->method('execute')
|
||||
|
||||
@@ -48,7 +48,6 @@ class SecondLevelCacheCountQueriesTest extends SecondLevelCacheFunctionalTestCas
|
||||
|
||||
if ($cacheUsage === 0) {
|
||||
$metadataCacheReflection = new ReflectionProperty(ClassMetadata::class, 'cache');
|
||||
$metadataCacheReflection->setAccessible(true);
|
||||
$metadataCacheReflection->setValue($metadata, null);
|
||||
|
||||
return;
|
||||
|
||||
@@ -11,6 +11,8 @@ use Doctrine\ORM\Mapping\Id;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function substr_count;
|
||||
|
||||
#[Group('DDC-3042')]
|
||||
class DDC3042Test extends OrmFunctionalTestCase
|
||||
{
|
||||
@@ -23,14 +25,18 @@ class DDC3042Test extends OrmFunctionalTestCase
|
||||
|
||||
public function testSQLGenerationDoesNotProvokeAliasCollisions(): void
|
||||
{
|
||||
self::assertStringNotMatchesFormat(
|
||||
'%sfield11%sfield11%s',
|
||||
$this
|
||||
self::assertSame(
|
||||
1,
|
||||
substr_count(
|
||||
$this
|
||||
->_em
|
||||
->createQuery(
|
||||
'SELECT f, b FROM ' . __NAMESPACE__ . '\DDC3042Foo f JOIN ' . __NAMESPACE__ . '\DDC3042Bar b WITH 1 = 1',
|
||||
)
|
||||
->getSQL(),
|
||||
'field_11',
|
||||
),
|
||||
'The alias "field11" should only appear once in the SQL query.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket\GH10049;
|
||||
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use PHPUnit\Framework\Attributes\DoesNotPerformAssertions;
|
||||
|
||||
class GH10049Test extends OrmFunctionalTestCase
|
||||
{
|
||||
@@ -18,7 +19,7 @@ class GH10049Test extends OrmFunctionalTestCase
|
||||
);
|
||||
}
|
||||
|
||||
/** @doesNotPerformAssertions */
|
||||
#[DoesNotPerformAssertions]
|
||||
public function testInheritedReadOnlyPropertyValueCanBeSet(): void
|
||||
{
|
||||
$child = new ReadOnlyPropertyInheritor(10049);
|
||||
|
||||
@@ -54,8 +54,9 @@ class AbstractHydratorTest extends OrmFunctionalTestCase
|
||||
|
||||
$this->hydrator = $this
|
||||
->getMockBuilder(AbstractHydrator::class)
|
||||
->onlyMethods(['hydrateAllData'])
|
||||
->setConstructorArgs([$mockEntityManagerInterface])
|
||||
->getMockForAbstractClass();
|
||||
->getMock();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,7 +54,7 @@ use DoctrineGlobalArticle;
|
||||
use LogicException;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Group as TestGroup;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
|
||||
use ReflectionClass;
|
||||
use stdClass;
|
||||
|
||||
@@ -1126,7 +1126,7 @@ class ClassMetadataTest extends OrmTestCase
|
||||
$metadata->addLifecycleCallback('foo', 'bar');
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testGettingAnFQCNForNullIsDeprecated(): void
|
||||
{
|
||||
$metadata = new ClassMetadata(self::class);
|
||||
@@ -1165,7 +1165,7 @@ class ClassMetadataTest extends OrmTestCase
|
||||
);
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testDiscriminatorMapWithSameClassMultipleTimesDeprecated(): void
|
||||
{
|
||||
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issues/3519');
|
||||
|
||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace Doctrine\Tests\ORM\Mapping;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
|
||||
use Doctrine\DBAL\Platforms\SQLitePlatform;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\DefaultQuoteStrategy;
|
||||
use Doctrine\Tests\Models\NonPublicSchemaJoins\User as NonPublicSchemaUser;
|
||||
@@ -13,8 +13,6 @@ use Doctrine\Tests\OrmTestCase;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function assert;
|
||||
use function enum_exists;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
@@ -29,8 +27,7 @@ class DefaultQuoteStrategyTest extends OrmTestCase
|
||||
$em = $this->getTestEntityManager();
|
||||
$metadata = $em->getClassMetadata(NonPublicSchemaUser::class);
|
||||
$strategy = new DefaultQuoteStrategy();
|
||||
$platform = $this->getMockForAbstractClass(AbstractPlatform::class, enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : []);
|
||||
assert($platform instanceof AbstractPlatform);
|
||||
$platform = new SQLitePlatform();
|
||||
|
||||
self::assertSame(
|
||||
'readers.author_reader',
|
||||
|
||||
@@ -6,14 +6,14 @@ namespace Doctrine\Tests\ORM\Mapping;
|
||||
|
||||
use Doctrine\Deprecations\PHPUnit\VerifyDeprecations;
|
||||
use Doctrine\ORM\Mapping\Table;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class TableMappingTest extends TestCase
|
||||
{
|
||||
use VerifyDeprecations;
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testDeprecationOnIndexesPropertyIsTriggered(): void
|
||||
{
|
||||
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/pull/11357');
|
||||
@@ -21,7 +21,7 @@ final class TableMappingTest extends TestCase
|
||||
new Table(indexes: []);
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testDeprecationOnUniqueConstraintsPropertyIsTriggered(): void
|
||||
{
|
||||
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/pull/11357');
|
||||
|
||||
@@ -11,9 +11,9 @@ use Doctrine\ORM\Mapping\Driver\AttributeDriver;
|
||||
use Doctrine\ORM\Mapping\Driver\XmlDriver;
|
||||
use Doctrine\ORM\ORMSetup;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use PHPUnit\Framework\Attributes\RequiresSetting;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ReflectionProperty;
|
||||
use Symfony\Component\Cache\Adapter\AbstractAdapter;
|
||||
@@ -28,7 +28,7 @@ class ORMSetupTest extends TestCase
|
||||
{
|
||||
use VerifyDeprecations;
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testAttributeConfiguration(): void
|
||||
{
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
@@ -51,7 +51,7 @@ class ORMSetupTest extends TestCase
|
||||
self::assertInstanceOf(AttributeDriver::class, $config->getMetadataDriverImpl());
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testXMLConfiguration(): void
|
||||
{
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
@@ -104,7 +104,7 @@ class ORMSetupTest extends TestCase
|
||||
}
|
||||
|
||||
#[Group('DDC-1350')]
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testConfigureProxyDir(): void
|
||||
{
|
||||
$config = ORMSetup::createAttributeMetadataConfiguration([], true, '/foo');
|
||||
|
||||
@@ -68,8 +68,7 @@ class BasicEntityPersisterTypeValueSqlTest extends OrmTestCase
|
||||
|
||||
$platform = $this->getMockBuilder(AbstractPlatform::class)
|
||||
->setConstructorArgs(enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : [])
|
||||
->onlyMethods(['supportsIdentityColumns'])
|
||||
->getMockForAbstractClass();
|
||||
->getMock();
|
||||
$platform->method('supportsIdentityColumns')
|
||||
->willReturn(true);
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@ namespace Doctrine\Tests\ORM\Persisters;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Driver;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
|
||||
use Doctrine\DBAL\Platforms\SQLitePlatform;
|
||||
use Doctrine\ORM\Persisters\Collection\ManyToManyPersister;
|
||||
use Doctrine\Tests\Models\ManyToManyPersister\ChildClass;
|
||||
use Doctrine\Tests\Models\ManyToManyPersister\OtherParentClass;
|
||||
@@ -16,8 +15,6 @@ use Doctrine\Tests\OrmTestCase;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function enum_exists;
|
||||
|
||||
#[CoversClass(ManyToManyPersister::class)]
|
||||
final class ManyToManyPersisterTest extends OrmTestCase
|
||||
{
|
||||
@@ -34,7 +31,7 @@ final class ManyToManyPersisterTest extends OrmTestCase
|
||||
->onlyMethods(['executeStatement', 'getDatabasePlatform'])
|
||||
->getMock();
|
||||
$connection->method('getDatabasePlatform')
|
||||
->willReturn($this->getMockForAbstractClass(AbstractPlatform::class, enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : []));
|
||||
->willReturn(new SQLitePlatform());
|
||||
|
||||
$parent = new ParentClass(1);
|
||||
$otherParent = new OtherParentClass(42);
|
||||
|
||||
@@ -22,9 +22,9 @@ use Doctrine\Tests\Models\Company\CompanyPerson;
|
||||
use Doctrine\Tests\Models\ECommerce\ECommerceFeature;
|
||||
use Doctrine\Tests\OrmTestCase;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
|
||||
use PHPUnit\Framework\Attributes\RequiresMethod;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhp;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
use stdClass;
|
||||
@@ -251,7 +251,7 @@ class ProxyFactoryTest extends OrmTestCase
|
||||
|
||||
#[RequiresPhp('8.4')]
|
||||
#[RequiresMethod(ProxyHelper::class, 'generateLazyGhost')]
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testProxyFactoryTriggersDeprecationWhenNativeLazyObjectsAreDisabled(): void
|
||||
{
|
||||
$this->emMock->getConfiguration()->enableNativeLazyObjects(false);
|
||||
|
||||
@@ -37,7 +37,7 @@ class ParserResultTest extends TestCase
|
||||
|
||||
public function testSetGetSqlExecutor(): void
|
||||
{
|
||||
$executor = $this->getMockForAbstractClass(AbstractSqlExecutor::class);
|
||||
$executor = $this->createMock(AbstractSqlExecutor::class);
|
||||
$this->parserResult->setSqlExecutor($executor);
|
||||
self::assertSame($executor, $this->parserResult->getSqlExecutor());
|
||||
}
|
||||
|
||||
@@ -596,12 +596,11 @@ class QueryTest extends OrmTestCase
|
||||
{
|
||||
$driverConnection = $this->createMock(Driver\Connection::class);
|
||||
$driverConnection->method('query')
|
||||
->will($this->onConsecutiveCalls(...$results));
|
||||
->willReturnOnConsecutiveCalls(...$results);
|
||||
|
||||
$platform = $this->getMockBuilder(AbstractPlatform::class)
|
||||
->setConstructorArgs(enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : [])
|
||||
->onlyMethods(['supportsIdentityColumns'])
|
||||
->getMockForAbstractClass();
|
||||
->getMock();
|
||||
$platform->method('supportsIdentityColumns')
|
||||
->willReturn(true);
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ class DefaultRepositoryFactoryTest extends TestCase
|
||||
private function buildClassMetadata(string $className): ClassMetadata&MockObject
|
||||
{
|
||||
$metadata = $this->createMock(ClassMetadata::class);
|
||||
$metadata->method('getName')->will(self::returnValue($className));
|
||||
$metadata->method('getName')->willReturn($className);
|
||||
$metadata->name = $className;
|
||||
|
||||
$metadata->customRepositoryClassName = null;
|
||||
|
||||
@@ -30,8 +30,7 @@ class PaginatorTest extends OrmTestCase
|
||||
{
|
||||
$platform = $this->getMockBuilder(AbstractPlatform::class)
|
||||
->setConstructorArgs(enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : [])
|
||||
->onlyMethods(['supportsIdentityColumns'])
|
||||
->getMockForAbstractClass();
|
||||
->getMock();
|
||||
$platform->method('supportsIdentityColumns')
|
||||
->willReturn(true);
|
||||
|
||||
|
||||
@@ -570,8 +570,7 @@ class UnitOfWorkTest extends OrmTestCase
|
||||
{
|
||||
$platform = $this->getMockBuilder(AbstractPlatform::class)
|
||||
->setConstructorArgs(enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : [])
|
||||
->onlyMethods(['supportsIdentityColumns'])
|
||||
->getMockForAbstractClass();
|
||||
->getMock();
|
||||
$platform->method('supportsIdentityColumns')
|
||||
->willReturn(true);
|
||||
|
||||
|
||||
@@ -539,7 +539,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
$conn = static::$sharedConn;
|
||||
|
||||
// In case test is skipped, tearDown is called, but no setup may have run
|
||||
if (! $conn) {
|
||||
if (! $conn || ! isset($this->_em)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ abstract class OrmTestCase extends TestCase
|
||||
$connection = $this->getMockBuilder(Connection::class)
|
||||
->setConstructorArgs([[], $this->createDriverMock($platform)])
|
||||
->onlyMethods(['quote'])
|
||||
->getMockForAbstractClass();
|
||||
->getMock();
|
||||
$connection->method('quote')->willReturnCallback(static fn (string $input) => sprintf("'%s'", $input));
|
||||
|
||||
return $connection;
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Doctrine\Tests\Proxy;
|
||||
|
||||
use Doctrine\ORM\Proxy\Autoloader;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use function class_exists;
|
||||
@@ -32,7 +32,7 @@ class AutoloaderTest extends TestCase
|
||||
|
||||
/** @param class-string $className */
|
||||
#[DataProvider('dataResolveFile')]
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testResolveFile(
|
||||
string $proxyDir,
|
||||
string $proxyNamespace,
|
||||
@@ -43,7 +43,7 @@ class AutoloaderTest extends TestCase
|
||||
self::assertEquals($expectedProxyFile, $actualProxyFile);
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
#[IgnoreDeprecations]
|
||||
public function testAutoload(): void
|
||||
{
|
||||
if (file_exists(sys_get_temp_dir() . '/AutoloaderTestClass.php')) {
|
||||
|
||||
Reference in New Issue
Block a user