Compare commits

...

129 Commits

Author SHA1 Message Date
Grégoire Paris
bf449bef7d Merge pull request #10737 from nicolas-grekas/lexer-deprec 2023-06-01 11:35:50 +02:00
Nicolas Grekas
152f91fa33 Fix deprecations from doctrine/lexer 2023-06-01 11:22:36 +02:00
Grégoire Paris
14d1eb5340 Document pdo_sqlite requirement for tests (#10734) 2023-06-01 08:57:07 +02:00
Grégoire Paris
da0998c401 Add missing underscore to RST links (#10731) 2023-05-30 23:00:28 +02:00
Grégoire Paris
cc011d8215 Merge pull request #10725 from doctrine/2.14.x
Merge 2.14.x up into 2.15.x
2023-05-24 14:08:21 +02:00
Grégoire Paris
d831c126c9 Merge pull request #10643 from htto/bugfix/sti-with-abstract-intermediate
Fix single table inheritance with intermediate abstract class(es)
2023-05-24 11:58:11 +02:00
Grégoire Paris
10eae1a7ff Merge pull request #10722 from phansys/query_single_result_exception
Fix and improve functional test cases expecting `NonUniqueResultException` from `AbstractQuery::getSingleScalarResult()`
2023-05-23 22:46:18 +02:00
Javier Spagnoletti
125e18cf24 Fix and improve functional test cases expecting NonUniqueResultException from AbstractQuery::getSingleScalarResult() 2023-05-23 05:32:38 -03:00
Grégoire Paris
8fba9d6868 Merge pull request #10708 from mbabker/2.15-link-fix 2023-05-16 17:06:17 +02:00
Michael Babker
7f4f1cda71 Correct docs link 2023-05-16 09:38:09 -05:00
Grégoire Paris
1c905b0e0a Merge pull request #10702 from greg0ire/fix-build 2023-05-15 11:53:09 +02:00
Grégoire Paris
7901790b97 Adapt to latest coding standards 2023-05-15 11:42:13 +02:00
Grégoire Paris
cef1d2d740 Merge pull request #10666 from MatTheCat/inherited-readonly-properties
Create `ReflectionReadonlyProperty` from their declaring class so their value can be set
2023-05-12 07:50:03 +02:00
Grégoire Paris
8126882305 Merge pull request #10486 from mpdude/fix-to-many-update-on-delete
Fix to-many collections left in dirty state after entities are removed by the UoW
2023-05-12 00:11:56 +02:00
Matthias Pigulla
a9513692cb Fix to-many collections left in dirty state after entities are removed by the UoW 2023-05-12 00:02:44 +02:00
Grégoire Paris
52c3d9d82a Merge pull request #10508 from Gwemox/fix-enum-identity
Fix id hash of entity with enum as identifier
2023-05-12 00:00:20 +02:00
MatTheCat
2f46e5a130 Rename test class and method 2023-05-11 09:36:43 +02:00
Mathieu
a3fa1d7faa Replace assertions by @doesNotPerformAssertions 2023-05-11 09:33:12 +02:00
MatTheCat
c7c57be0c2 Create ReflectionReadonlyProperty from their declaring class so their value can be set 2023-05-11 09:33:12 +02:00
MatTheCat
721794fb9c Add test case 2023-05-11 09:33:12 +02:00
Terence Eden
70477d81e9 Documentation typo (#10686)
The past tense of spin is spun, not "spinned"

https://en.wiktionary.org/wiki/spin#English
2023-05-08 12:22:09 +02:00
Alexander M. Turek
9bc6f5b4ac Support unserializing 2.14 ParserResult instances (#10684) 2023-05-07 20:56:25 +02:00
Grégoire Paris
60c625be17 Upgrade to Psalm 5.11.0 (#10679) 2023-05-05 07:21:05 +02:00
Grégoire Paris
8b0d6a13c2 Merge pull request #10671 from BoShurik/fix-attribute-many-to-many-mapping
Fix attribute ManyToMany mapping
2023-05-04 23:52:47 +02:00
Grégoire Paris
a7ac6ff8d9 Merge pull request #10677 from greg0ire/psalm-5-10
Upgrade to Psalm 5.10.0
2023-05-04 23:49:02 +02:00
Grégoire Paris
222d544b0c Upgrade to Psalm 5.10.0 2023-05-04 22:12:31 +02:00
ixitheblue
6f1fd7a81e Fix iteration index initialisation (#10675)
In the code examples of the use of the ``Query#toIterable()`` method, an index ``$i`` is used to control the size of the current batch, which ends when the condition ``($i % $batchSize) === 0`` becomes true.

Because this condition is preceded by ``++$i`` and ``$i`` is initialized to 1, the first batch is actually of size ``$batchSize - 1`` instead of ``$batchSize``.

To solve this, ``$i`` should be initialized to 0 instead of 1.
2023-05-04 14:43:56 +02:00
BoShurik
2af6e4db38 Take into account join columns specifications.
Currently, the AttributeDriver ignores any join column attribute specified on a many to many relationship.
Let's copy code from the AnnotationDriver to fix that.

Fixes #9902
2023-05-04 15:36:29 +03:00
BoShurik
b48dafded8 Update doc-block for AttributeDriverTest's fixtures 2023-05-04 15:35:40 +03:00
Grégoire Paris
ffe1550a68 Bump version numbers in the README (#10674)
2.15.0 has been released.
2023-05-04 13:44:58 +02:00
Grégoire Paris
eef5a1db81 Merge pull request #10668 from stollr/doc_attr_uniqueconstraint
Added doc for the fields parameter of the UniqueConstraint attribute
2023-05-04 08:13:33 +02:00
Grégoire Paris
c2d053d185 Update branch metadata (#10672) 2023-05-03 22:41:13 +02:00
stollr
77822d623e Added doc for the fields parameter of the UniqueConstraint attribute 2023-05-03 10:45:07 +02:00
Grégoire Paris
7b5fafffbe Merge pull request #10654 from mpdude/join-column-does-not-make-it-own
Deprecate usage of `@JoinColumn` on the inverse side of one-to-one associations
2023-04-26 20:52:02 +02:00
Matthias Pigulla
aba8d74017 Deprecate usage of @JoinColumn on the inverse side of one-to-one associations
Following up on #10652:

 #### Current situation

The implementation of `\Doctrine\ORM\Mapping\ClassMetadataInfo::_validateAndCompleteOneToOneMapping` will consider a field with a one-to-one association to be the owning side also when it configures `@JoinColumn` settings.

 #### Suggested change

For a one to one association, a field should be the inverse side when it uses the `mappedBy` attribute, and be the owning side otherwise. The `JoinColumn` may be configured on the owning side only.

This PR adds a deprecation notice when `@JoinColumn` is used on the side of a one-to-one association where `mappedBy` occurs.

In 3.0, this will throw a `MappingException`.
2023-04-25 15:29:17 +02:00
Alexander M. Turek
a056552db9 Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  PHPStan 1.10.14 (#10655)
  Remove JoinColumn from inverse side (#10652)
  Apply `SlevomatCodingStandard.Commenting.AnnotationName` CS rule (#10653)
2023-04-25 13:43:39 +02:00
Alexander M. Turek
1142a396d3 PHPStan 1.10.14 (#10655) 2023-04-25 13:32:39 +02:00
Grégoire Paris
f01b7d254d Remove JoinColumn from inverse side (#10652)
This makes no sense because it describes a one-to-one where each table
references the other one. I do not think this is deliberately supported,
and it probably will not be supported at all in 3.0.
2023-04-25 13:16:20 +02:00
Javier Spagnoletti
1ea8424e07 Apply SlevomatCodingStandard.Commenting.AnnotationName CS rule (#10653) 2023-04-25 08:56:58 +02:00
Grégoire Paris
ba9f51a363 Merge pull request #10648 from doctrine/2.14.x-merge-up-into-2.15.x_VZV5I0St
Merge release 2.14.3 into 2.15.x
2023-04-22 15:45:17 +02:00
Heiko Przybyl
1ae74b8ec5 Fix single table inheritance with intermediate abstract class(es)
Fixes #10625
2023-04-20 15:37:42 +02:00
Grégoire Paris
a64f315dfe Merge pull request #10642 from yobrx/patch-1 2023-04-20 11:46:32 +02:00
Yoann B
6ca319a6f4 fix array association on partial index 2023-04-20 10:59:39 +02:00
Grégoire Paris
fceb279947 Merge pull request #10630 from monadial/fix/fqcn-type-in-xml-mapping
Fixed xsd schema for support FQCN type
2023-04-16 10:26:37 +02:00
Alexander M. Turek
2977933119 Run tests on SQLite with foreign keys enabled (#10632) 2023-04-15 10:54:31 +02:00
Tomas Mihalicka
5ac6fadf29 Fixed xsd schema for support FQCN type
After update to orm 2.14.2 invalid xsd schema error is occured, when in field,id or attribute-override have type is FQCN
2023-04-14 18:16:35 +02:00
Grégoire Paris
e59ed88251 Merge pull request #10620 from ecourtial/fix-doc-typo
fix typo in HydrationCompleteHandler doc
2023-04-12 21:21:42 +02:00
Eric COURTIAL
a16aeaeac8 fix typo in HydrationCompleteHandler doc 2023-04-12 21:02:36 +02:00
Mathieu
fca1ef78a7 Handle null comparisons in ManyToManyPersister (#10587)
* Add test case for https://github.com/doctrine/orm/issues/7717

* Do not hide null equality checks in `SqlValueVisitor::walkComparison`

* Annotate `GH7717Parent::$children` type
2023-04-12 17:31:38 +02:00
Grégoire Paris
a78e5bcf65 Merge pull request #10519 from mpdude/deprecate-override-association
Deprecate overriding associations not inherited from a mapped superclass
2023-04-07 20:03:39 +02:00
Thibault Buathier
09b4a75ed3 Fix id hash of entity with enum as identifier
When an entity have a backed enum as identifier, `UnitOfWork` tries to
cast to string when generating the hash of the id.
This fix calls `->value` when identifier is a `BackedEnum`.
Fixes #10471
Fixes #10334
2023-04-03 17:20:48 +02:00
Grégoire Paris
b984b567b8 Merge pull request #10599 from amina-seraoui/2.14.x
fix(persistent-collection): check association is not nullable before using it as an array
2023-04-02 23:26:11 +02:00
tasmim-concept
92c56164ee throw exception if association is null 2023-04-01 08:50:06 +02:00
Grégoire Paris
b2707509fc Merge pull request #10605 from greg0ire/2.15.x
Merge 2.14.x up into 2.15.x
2023-03-30 20:37:50 +02:00
Grégoire Paris
1d02139d2a Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-03-30 17:22:56 +02:00
Grégoire Paris
7ed28dba50 Merge pull request #10601 from JanTvrdik/discriminated-column-options 2023-03-30 13:31:59 +02:00
Jan Tvrdík
f215515bab Support options like charset and collation on DiscriminatedColumn
[closes #10462]
2023-03-30 11:58:29 +02:00
Grégoire Paris
ffbfbfcda1 Merge pull request #10602 from greg0ire/remove-or
Remove duplicate array shape
2023-03-29 23:30:10 +02:00
Grégoire Paris
4a30f622ec Remove duplicate array shape
DiscriminatorColumnMapping is just a specialization of the array shape
that is right of the pipe: it has the same fields, except fewer fields
are nullable. The union of that is the same thing as the array shape.
2023-03-29 21:58:36 +02:00
Grégoire Paris
aec3556502 Merge pull request #10554 from mpdude/mapped-superclass-resolve-to-many-lazy-check
Make "targetEntity must not be a mapped superclass" a lazy check
2023-03-24 08:27:38 +01:00
Gabriel Ostrolucký
25bd41a504 Merge branch '2.14.x' into 2.15.x 2023-03-19 22:46:07 +01:00
Grégoire Paris
04573fc283 Address deprecation of fetchAll() (#10569)
The methods Connection::fetchAll() and Result::fetchAll() have been
deprecated in favor of more their precise counterparts.
2023-03-07 13:17:42 +01:00
Alexander M. Turek
82362ee65e Merge 2.14.x into 2.15.x (#10564) 2023-03-06 09:30:02 +01:00
Alexander M. Turek
9ff0440aac Merge 2.14.x into 2.15.x (#10561) 2023-03-05 22:35:31 +01:00
Matthias Pigulla
2c40e917c8 Revert unnecessary changes from #10473 2023-03-01 21:30:22 +00:00
Matthias Pigulla
5c06d46874 Add tests for the schema validator check 2023-03-01 21:30:22 +00:00
Matthias Pigulla
24c4ac4dd8 Do not check at runtime that associations do not refer to mapped superclasses 2023-03-01 20:40:55 +00:00
Grégoire Paris
4fad7a1190 Merge pull request #10473 from mpdude/mapped-superclass-resolve-to-many
Allow to-many associations on mapped superclasses w/ ResolveTargetEntityListener
2023-03-01 08:16:07 +01:00
Alexander M. Turek
f36a8c879c Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Ignore the cache dir of PHPUnit 10 (#10546)
  Make data providers static (#10544)
  Bump dev tools (#10541)
  Mark SqlWalker methods as not deprecated (#10540)
  docs: consistency order for docblock in association mapping (#10534)
  Correct use of PHP attribute
  fix typo in faq.rst (#10526)
  fix: use executeStatement in SchemaTool (#10516)
  Write a test in a more specific way
  Put up a warning sign that mapping may not be inherited from transient classes (#10392)
  Avoid unnecessary information in query hints to improve query cache hit ratio
2023-02-28 13:50:36 +01:00
Alexander M. Turek
fa4b945b94 Make data providers static (#10545) 2023-02-28 08:29:47 +01:00
Matthias Pigulla
7814cbf4ec Fix a Markdown/RST formatting glitch 2023-02-24 17:59:02 +01:00
Grégoire Paris
979b3dcb8d Merge pull request #10513 from greg0ire/use-array-shapes
Use array shapes where appropriate
2023-02-13 23:57:57 +01:00
Matthias Pigulla
8efdcb0555 Deprecate overriding associations not inherited from a mapped superclass 2023-02-13 20:46:11 +00:00
Grégoire Paris
3810a0b6f9 Merge pull request #10470 from mpdude/prevent-entity-override
Deprecate overriding fields/associations inherited from other entities
2023-02-12 18:30:46 +01:00
Matthias Pigulla
c9b644dced Trigger a deprecation notice when entity fields/associations are overridden
This was brought up in #8348, but seemingly forgotten to be implenented in later versions.

Closes #10289.
2023-02-09 22:15:05 +00:00
Grégoire Paris
ae6de13c01 Use array shapes where appropriate
Working on converting these array shapes to DTO allowed me to find every
signature where they are supposed to be used.

The Psalm baseline gets worse because it considers accessing an array
key differently depending on whether it is defined vaguely, as
array<string, mixed>, or precisely, as array{my-key?: string}.
2023-02-09 19:44:47 +01:00
Matthias Pigulla
072c40357f Add mapping configurations for classes that were used in tests as entities, but never declared
Now that we validate association targets, that's an error.
2023-02-08 21:11:59 +00:00
Matthias Pigulla
ca94e82828 Allow to-many associations on mapped superclasses w/ ResolveTargetEntityListener
Allow to-many associations to be used on mapped superclasses when the owning (inverse) side does not refer back to the mapped superclass, thanks to `ResolveTargetEntityListener`.

 #### Current situation

The [documentation states](https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html):

> No database table will be created for a mapped superclass itself

> [...] persistent relationships defined by a mapped superclass must be unidirectional (with an owning side only). This means that One-To-Many associations are not possible on a mapped superclass at all.

That's a though limitation.

~Obviously~ ~apparently~ Probably the limitation comes from the fact that in a to-many association the "many" side has to hold a foreign key. Since the mapped superclass does not have a database table (it's not an entity), no such backreference can be established.

Currently, to-many associations trigger an exception as soon as they are seen on a mapped superclass:

d6c0031d44/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php (L459-L461)

 #### `ResolveTargetEntityListener`

The `ResolveTargetEntityListener` can be used to substitute interface or class names in mapping configuration at runtime, during the metadata load phase.

When this gimmick is used to replace _all_ references to the mapped superclass with an entity class in time, it should be possible to have to-many associations on the inheriting entity classes.

 #### Suggested solution

Instead of rejecting to-many associations on mapped superclasses right away, validate that at the end of the day (after the `loadClassMetadata` event has been processed) no association may target at a non-entity class. That includes mapped superclasses as well as transient classes.

 #### Motivating example

Consider a library that comes with a `User` base class. This class is `abstract` and has to be subclassed/filled when the library is used.

By making this a mapped superclass, library users have the freedom to either have a simple user entity class or a user class hierarchy, but we do not impose any requirements on them. (NB we also don't want to have a root entity in the library, because that would have to declare the entire class hierarchy, including library users' classes.)

The actual user class to be used will be configured through the `ResolveTargetEntityListener`.

The library also includes a `SocialMediaAccount` entity. A `User` can have multiple of these accounts, and we want to be able to navigate the accounts from the user side.

To make the example even more fancy, there is a self-referencing association on the `User`: A `User` has been created by another user, and holds a collection of all other `User`s it created.

The test case contained in this PR contains this example and validates that all association mappings look just as if the final user class had been written as an entity directly, without the superclass.

 #### Potential review talking points

- Am I missing other reasons why to-many is not feasible?
- We now reject association mappings with `targetEntity`s that are not entities; relevant BC break? (IMHO: no.)

 #### Review tip

Review commit by commit, not all files at once. The last commit adds a lot of entity declarations that were previously missed in tests and now raised exceptions; that's a lot of clutter in the PR.
2023-02-08 21:11:58 +00:00
Grégoire Paris
db0b9d13c6 Merge pull request #10511 from doctrine/2.14.x
Merge 2.14.x up into 2.15.x
2023-02-08 22:07:14 +01:00
Alexander M. Turek
6c17e47624 Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Remove calls to assertObjectHasAttribute() (#10502)
  Remove calls to withConsecutive() (#10501)
  Use recognized array key
  Fix #9095 by re-applying #9096
  Use linebreaks
2023-02-07 01:21:39 +01:00
Grégoire Paris
83d56d75e1 Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-02-04 10:09:15 +01:00
Grégoire Paris
d593c33ffa Merge pull request #10478 from greg0ire/better-psalm-type-location
Move psalm types to ClassMetadata
2023-01-28 16:35:37 +01:00
Grégoire Paris
6c925f5b60 Move psalm types to ClassMetadata
This spares us from referencing ClassMetadataInfo from other classes,
which is a good thing since it is deprecated. It also means merging up
is easier.
2023-01-28 15:40:27 +01:00
Grégoire Paris
82bf68d482 Remove underscore prefix on private variables (#10477) 2023-01-28 15:33:34 +01:00
Alexander M. Turek
2ee936acb4 Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Psalm 5.6.0, PHPStan 1.9.14 (#10468)
2023-01-26 19:08:35 +01:00
Matthias Pigulla
843bff4971 Fix some tests that were missed in #10431 (#10464)
In #10431, some invalid inheritance declarations in our test base were fixed. However, the change missed to update XML, PHP and static PHP mapping configurations as well.

Apparently, this did not raise any flags because the misconfiguration only caused a deprecation notice in 2.15.x. Running the tests against 3.0 (where the misconfiguration will be an error) unveiled the mistake.
2023-01-26 19:04:57 +01:00
Matthias Pigulla
d679292861 Remove commented-out code sections (#10465)
This removes comments added in #10431 on the 2.15.x branch, as suggested in https://github.com/doctrine/orm/pull/10460#issuecomment-1404889903.
2023-01-26 14:09:35 +01:00
Matthias Pigulla
65687821a7 Deprecate undeclared entity inheritance (#10431)
Inheritance has to be declared as soon as one entity class extends (directly or through middle classes) another one.

This is also pointed out in the opening comment for #8348:

> Entities are not allowed to extend from entities without an inheritence mapping relationship (Single Table or Joined Table inheritance). [...] While Doctrine so far allowed these things, they are fragile and will break on certain scenarios.

Throwing an exception in case of this misconfiguration is nothing we should do light-heartedly, given that it may surprise users in a bugfix or feature release. So, we should start with a deprecation notice  and make this an exception in 3.0. The documentation is updated accordingly at #10429.

Catching missing inheritance declarations early on is important to avoid weird errors further down the road, giving users a clear indication of the root cause.

In case you are affected by this, please understand that although things "previously worked" for you, you have been using the ORM outside of what it was designed to do. That may have worked in simple cases, but may also have caused invalid results (wrong or missing data after hydration?) that possibly went unnoticed in subtle cases.
2023-01-24 22:47:27 +01:00
Grégoire Paris
ca0dffb53e Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-01-23 19:27:03 +01:00
Grégoire Paris
01028cf3b8 Merge commit '8b2854393' into 2.15.x 2023-01-23 19:20:22 +01:00
Grégoire Paris
84bfe7cbb9 Merge pull request #10446 from greg0ire/update-psalm-baseline
Update Psalm baseline
2023-01-23 19:20:00 +01:00
Grégoire Paris
1b3978e8c9 Update Psalm baseline 2023-01-23 19:17:40 +01:00
Grégoire Paris
7f783b59c8 Merge pull request #10442 from greg0ire/embedded-class-array-shape 2023-01-23 10:58:11 +01:00
Grégoire Paris
68662f5920 Add embedded class mapping array shape
This should be replaced with a DTO in the next major.
To be able to have something usable, I had to move the validation of the
DTO (checking that it has a "class" attribute) to mapEmbedded, which
happens earlier than doLoadMetadata(). It is unclear to me why it was
not put here in the first place.
2023-01-22 23:49:43 +01:00
Adrien Crivelli
769b161dff Identity map cannot contain null value (#10156) 2023-01-22 14:15:20 +07:00
Grégoire Paris
9857cf971b Merge pull request #10438 from greg0ire/2.15.x
Merge 2.14.x up into 2.15.x
2023-01-20 23:58:44 +01:00
Grégoire Paris
f73dae9bc4 Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-01-20 21:19:28 +01:00
Grégoire Paris
1c357b9fb3 Merge pull request #10426 from mpdude/parent-classes-docblock
Slight docblock improvements for `CM::parentClasses`
2023-01-20 12:46:34 +01:00
Matthias Pigulla
3d031ed541 Slight docblock improvements for CM::parentClasses 2023-01-20 11:26:28 +00:00
Grégoire Paris
15ed97b7b1 Merge pull request #10437 from greg0ire/update-baseline
Update Psalm baseline
2023-01-20 12:03:42 +01:00
Grégoire Paris
9fd4af23e1 Update Psalm baseline 2023-01-20 12:00:34 +01:00
Grégoire Paris
4206f01e7b Use FieldMapping array shape even more (#10430)
I experimented on converting FieldMapping to a DTO, and it allowed me to
find more places where it should be used.
2023-01-19 10:06:03 +01:00
Matthias Pigulla
7d4052c9e7 Fix version number in UPGRADE.md (#10428)
This was a mistake in #10423.
2023-01-19 08:23:27 +01:00
Grégoire Paris
fc6feb5938 Merge pull request #10423 from mpdude/deprecate-table-type-per-class
Add deprecations for "table per class" inheritance
2023-01-18 23:23:53 +01:00
Matthias Pigulla
89b98bdff9 Add deprecations for "table per class" inheritance 2023-01-18 16:30:57 +00:00
Grégoire Paris
37572802cc Reuse association mapping array shape (#10403) 2023-01-17 11:27:42 +01:00
Grégoire Paris
a5bdc619c7 Merge pull request #10408 from greg0ire/field-mapping-improvements
Field mapping improvements
2023-01-17 09:08:33 +01:00
Grégoire Paris
65a7c8882f Merge pull request #10413 from doctrine/2.14.x-merge-up-into-2.15.x_2sgwy6Oi
Merge release 2.14.1 into 2.15.x
2023-01-16 20:44:54 +01:00
Grégoire Paris
2d6295c9db Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-01-16 20:24:44 +01:00
Alexander M. Turek
f0616626e0 Test with a stable PHPUnit (#10406) 2023-01-16 15:53:19 +07:00
Matthias Pigulla
a8ef69dbe6 Factor out logic that tracks mapping inheritance (#10397) 2023-01-16 06:33:54 +04:00
Grégoire Paris
c0a7317e8d Reuse array shape 2023-01-15 21:55:32 +01:00
Grégoire Paris
843b0fcc16 Add missing fields 2023-01-15 21:55:32 +01:00
Grégoire Paris
b56de5b0e2 Type TypedFieldMapper API more precisely 2023-01-15 21:55:32 +01:00
Alexander M. Turek
0b35e637b8 Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Stop allowing phpbench's master branch
2023-01-15 14:54:24 +07:00
Grégoire Paris
277614d9c2 Merge pull request #10400 from doctrine/2.14.x
Merge 2.14.x up into 2.15.x
2023-01-14 11:10:20 +01:00
Alexander M. Turek
29b8b0bffb Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  PHPStan 1.9.8, Psalm 5.4.0 (#10382)
  fix typo for missing a comma (#10377)
  Docs: Removing `type: 'integer'` from mappings (#10368)
  Docs: Moving *attributes* mapping to first position (#10364)
  Docs: Deleting duplicate mapping example (#10363)
2023-01-09 11:32:00 +07:00
Grégoire Paris
b7ba018f0a Use more precise types for class strings (#10381) 2023-01-09 11:29:56 +07:00
Grégoire Paris
72b1bf0c02 Use the same type as in the DBAL (#10372)
* Use the same type as in the DBAL

Implementations pass this parameter unchanged to DBAL methods.

* Update Psalm baseline
2023-01-04 19:32:28 +01:00
Grégoire Paris
70241d3407 Merge pull request #10365 from greg0ire/precise-return-type
Address new behavior of $firstResult
2023-01-03 23:55:01 +01:00
Grégoire Paris
1d5d47964c Address new behavior of $firstResult
Following 1915dcd1e8, 0 is now used as a
default value, and Query::$firstResult is no longer nullable, but it
seems getFirstResult() was overlooked. The class is final, so this is no
breaking change.
2023-01-03 21:29:09 +01:00
Alexander M. Turek
c9c4203a1e Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  PHPStan 1.9.5 (#10359)
2023-01-02 23:14:10 +01:00
Grégoire Paris
091da8c420 Merge pull request #10329 from greg0ire/drop-lexer-1-backport
Drop doctrine/lexer 1
2023-01-02 21:07:13 +01:00
Alexander M. Turek
515a3d8b8b Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Shorter deprecation message (#10357)
  Add Fully-Qualified class name in UnrecognizedField exception to ease debugging (#10342)
  Include parameter types in hydration cache key generation (#10355)
2022-12-31 17:45:59 +01:00
Grégoire Paris
603ab9a185 Drop doctrine/lexer 1 2022-12-31 00:20:27 +01:00
Alexander M. Turek
10d27c18ea Allow doctrine/instantiator 2 (#10351) 2022-12-30 19:52:12 +01:00
Alexander M. Turek
ae9fb8ca21 Merge 2.14.x into 2.15.x (#10344) 2022-12-28 17:23:15 +01:00
Rémi San
c7f2a1d580 Support of NOT expression from doctrine/collections ^2.1 (#10234) 2022-12-28 17:22:39 +01:00
Grégoire Paris
b3f441cb8b Merge pull request #10330 from doctrine/2.14.x
Merge 2.14.x up into 2.15.x
2022-12-20 20:07:49 +01:00
301 changed files with 3308 additions and 1984 deletions

View File

@@ -12,21 +12,27 @@
"upcoming": true
},
{
"name": "2.15",
"branchName": "2.15.x",
"slug": "2.15",
"name": "2.16",
"branchName": "2.16.x",
"slug": "2.16",
"upcoming": true
},
{
"name": "2.14",
"branchName": "2.14.x",
"slug": "2.14",
"name": "2.15",
"branchName": "2.15.x",
"slug": "2.15",
"current": true,
"aliases": [
"current",
"stable"
]
},
{
"name": "2.14",
"branchName": "2.14.x",
"slug": "2.14",
"maintained": false
},
{
"name": "2.13",
"branchName": "2.13.x",

View File

@@ -40,6 +40,11 @@ cd orm
composer install
```
You will also need to enable the PHP extension that provides the SQLite driver
for PDO: `pdo_sqlite`. How to do so depends on your system, but checking that it
is enabled can universally be done with `php -m`: that command should list the
extension.
To run the testsuite against another database, copy the ``phpunit.xml.dist``
to for example ``mysql.phpunit.xml`` and edit the parameters. You can
take a look at the ``ci/github/phpunit`` directory for some examples. Then run:

View File

@@ -1,7 +1,7 @@
| [3.0.x][3.0] | [2.14.x][2.14] | [2.13.x][2.13] |
| [3.0.x][3.0] | [2.16.x][2.16] | [2.15.x][2.15] |
|:----------------:|:----------------:|:----------:|
| [![Build status][3.0 image]][3.0] | [![Build status][2.14 image]][2.14] | [![Build status][2.13 image]][2.13] |
| [![Coverage Status][3.0 coverage image]][3.0 coverage]| [![Coverage Status][2.14 coverage image]][2.14 coverage] | [![Coverage Status][2.13 coverage image]][2.13 coverage] |
| [![Build status][3.0 image]][3.0] | [![Build status][2.16 image]][2.16] | [![Build status][2.15 image]][2.15] |
| [![Coverage Status][3.0 coverage image]][3.0 coverage]| [![Coverage Status][2.16 coverage image]][2.16 coverage] | [![Coverage Status][2.15 coverage image]][2.15 coverage] |
[<h1 align="center">🇺🇦 UKRAINE NEEDS YOUR HELP NOW!</h1>](https://www.doctrine-project.org/stop-war.html)
@@ -22,11 +22,11 @@ without requiring unnecessary code duplication.
[3.0]: https://github.com/doctrine/orm/tree/3.0.x
[3.0 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.0.x/graph/badge.svg
[3.0 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.0.x
[2.14 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.14.x
[2.14]: https://github.com/doctrine/orm/tree/2.14.x
[2.14 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.14.x/graph/badge.svg
[2.14 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.14.x
[2.13 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.13.x
[2.13]: https://github.com/doctrine/orm/tree/2.13.x
[2.13 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.13.x/graph/badge.svg
[2.13 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.13.x
[2.16 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.16.x
[2.16]: https://github.com/doctrine/orm/tree/2.16.x
[2.16 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.16.x/graph/badge.svg
[2.16 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.16.x
[2.15 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.15.x
[2.15]: https://github.com/doctrine/orm/tree/2.15.x
[2.15 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.15.x/graph/badge.svg
[2.15 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.15.x

View File

@@ -1,3 +1,33 @@
# Upgrade to 2.15
## Deprecated configuring `JoinColumn` on the inverse side of one-to-one associations
For one-to-one associations, the side using the `mappedBy` attribute is the inverse side.
The owning side is the entity with the table containing the foreign key. Using `JoinColumn`
configuration on the _inverse_ side now triggers a deprecation notice and will be an error
in 3.0.
## Deprecated overriding fields or associations not declared in mapped superclasses
As stated in the documentation, fields and associations may only be overridden when being inherited
from mapped superclasses. Overriding them for parent entity classes now triggers a deprecation notice
and will be an error in 3.0.
## Deprecated undeclared entity inheritance
As soon as an entity class inherits from another entity class, inheritance has to
be declared by adding the appropriate configuration for the root entity.
## Deprecated stubs for "concrete table inheritance"
This third way of mapping class inheritance was never implemented. Code stubs are
now deprecated and will be removed in 3.0.
* `\Doctrine\ORM\Mapping\ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS` constant
* `\Doctrine\ORM\Mapping\ClassMetadataInfo::isInheritanceTypeTablePerClass()` method
* Using `TABLE_PER_CLASS` as the value for the `InheritanceType` attribute or annotation
or in XML configuration files.
# Upgrade to 2.14
## Deprecated `Doctrine\ORM\Persisters\Exception\UnrecognizedField::byName($field)` method.

View File

@@ -24,14 +24,14 @@
"composer-runtime-api": "^2",
"ext-ctype": "*",
"doctrine/cache": "^1.12.1 || ^2.1.1",
"doctrine/collections": "^1.5 || ^2.0",
"doctrine/collections": "^1.5 || ^2.1",
"doctrine/common": "^3.0.3",
"doctrine/dbal": "^2.13.1 || ^3.2",
"doctrine/deprecations": "^0.5.3 || ^1",
"doctrine/event-manager": "^1.2 || ^2",
"doctrine/inflector": "^1.4 || ^2.0",
"doctrine/instantiator": "^1.3",
"doctrine/lexer": "^1.2.3 || ^2",
"doctrine/instantiator": "^1.3 || ^2",
"doctrine/lexer": "^2",
"doctrine/persistence": "^2.4 || ^3",
"psr/cache": "^1 || ^2 || ^3",
"symfony/console": "^4.2 || ^5.0 || ^6.0",
@@ -40,16 +40,16 @@
},
"require-dev": {
"doctrine/annotations": "^1.13 || ^2",
"doctrine/coding-standard": "^9.0.2 || ^11.0",
"doctrine/coding-standard": "^9.0.2 || ^12.0",
"phpbench/phpbench": "^0.16.10 || ^1.0",
"phpstan/phpstan": "~1.4.10 || 1.10.6",
"phpstan/phpstan": "~1.4.10 || 1.10.14",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6",
"psr/log": "^1 || ^2 || ^3",
"squizlabs/php_codesniffer": "3.7.2",
"symfony/cache": "^4.4 || ^5.4 || ^6.0",
"symfony/var-exporter": "^4.4 || ^5.4 || ^6.2",
"symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"vimeo/psalm": "4.30.0 || 5.9.0"
"vimeo/psalm": "4.30.0 || 5.11.0"
},
"conflict": {
"doctrine/annotations": "<1.13 || >= 3.0"

View File

@@ -368,6 +368,7 @@ Optional parameters:
- **length**: By default this is 255.
- **columnDefinition**: By default this is null the definition according to the type will be used. This option allows to override it.
- **enumType**: By default this is `null`. Allows to map discriminatorColumn value to PHP enum
- **options**: See "options" attribute on :ref:`#[Column] <attrref_column>`.
.. _attrref_discriminatormap:
@@ -575,7 +576,7 @@ Example with partial indexes:
#[Index(name: "search_idx", columns: ["category"],
options: [
"where": "((category IS NOT NULL))"
"where" => "((category IS NOT NULL))"
]
)]
class ECommerceProduct
@@ -1104,7 +1105,8 @@ context.
Required parameters:
- **name**: Name of the Index
- **columns**: Array of columns.
- **fields**: Array of fields (the names of the properties, used in the entity class).
- **columns**: Array of columns (the names of the columns, used in the schema).
Optional parameters:

View File

@@ -86,7 +86,7 @@ with the batching strategy that was already used for bulk inserts:
<?php
$batchSize = 20;
$i = 1;
$i = 0;
$q = $em->createQuery('select u from MyProject\Model\User u');
foreach ($q->toIterable() as $user) {
$user->increaseCredit();
@@ -145,7 +145,7 @@ The following example shows how to do this:
<?php
$batchSize = 20;
$i = 1;
$i = 0;
$q = $em->createQuery('select u from MyProject\Model\User u');
foreach($q->toIterable() as $row) {
$em->remove($row);

View File

@@ -1304,14 +1304,13 @@ creating a class which extends ``AbstractHydrator``:
<?php
namespace MyProject\Hydrators;
use Doctrine\DBAL\FetchMode;
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
class CustomHydrator extends AbstractHydrator
{
protected function _hydrateAll()
{
return $this->_stmt->fetchAll(FetchMode::FETCH_ASSOC);
return $this->_stmt->fetchAllAssociative();
}
}

View File

@@ -15,22 +15,32 @@ is common to multiple entity classes.
Mapped superclasses, just as regular, non-mapped classes, can
appear in the middle of an otherwise mapped inheritance hierarchy
(through Single Table Inheritance or Class Table Inheritance).
(through Single Table Inheritance or Class Table Inheritance). They
are not query-able, and need not have an ``#[Id]`` property.
No database table will be created for a mapped superclass itself,
only for entity classes inheriting from it. Also, a mapped superclass
need not have an ``#[Id]`` property.
only for entity classes inheriting from it. That implies that a
mapped superclass cannot be the ``targetEntity`` in associations.
In other words, a mapped superclass can use unidirectional One-To-One
and Many-To-One associations where it is the owning side.
Many-To-Many associations are only possible if the mapped
superclass is only used in exactly one entity at the moment. For further
support of inheritance, the single or joined table inheritance features
have to be used.
.. note::
A mapped superclass cannot be an entity, it is not query-able and
persistent relationships defined by a mapped superclass must be
unidirectional (with an owning side only). This means that One-To-Many
associations are not possible on a mapped superclass at all.
Furthermore Many-To-Many associations are only possible if the
mapped superclass is only used in exactly one entity at the moment.
For further support of inheritance, the single or
joined table inheritance features have to be used.
One-To-Many associations are not generally possible on a mapped
superclass, since they require the "many" side to hold the foreign
key.
It is, however, possible to use the :doc:`ResolveTargetEntityListener <cookbook/resolve-target-entity-listener>`
to replace references to a mapped superclass with an entity class at runtime.
As long as there is only one entity subclass inheriting from the mapped
superclass and all references to the mapped superclass are resolved to that
entity class at runtime, the mapped superclass *can* use One-To-Many associations
and be named as the ``targetEntity`` on the owning sides.
.. warning::

View File

@@ -166,10 +166,10 @@ As long as the results are consistent with what a solution _without_ traits woul
have produced, this is probably fine.
However, to mention known limitations, it is currently not possible to use "class"
level `annotations <https://github.com/doctrine/orm/pull/1517>` or
level `annotations <https://github.com/doctrine/orm/pull/1517>`_ or
`attributes <https://github.com/doctrine/orm/issues/8868>` on traits, and attempts to
improve parser support for traits as `here <https://github.com/doctrine/annotations/pull/102>`
or `there <https://github.com/doctrine/annotations/pull/63>` have been abandoned
improve parser support for traits as `here <https://github.com/doctrine/annotations/pull/102>`_
or `there <https://github.com/doctrine/annotations/pull/63>`_ have been abandoned
due to complexity.
XML mapping configuration probably needs to completely re-configure or otherwise

View File

@@ -123,12 +123,12 @@ the ``FileDriver`` implementation for you to extend from:
class MyMetadataDriver extends FileDriver
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected $_fileExtension = '.dcm.ext';
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadMetadataForClass($className, ClassMetadata $metadata)
{
@@ -138,7 +138,7 @@ the ``FileDriver`` implementation for you to extend from:
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function _loadMappingFile($file)
{

View File

@@ -167,7 +167,7 @@ The API of the ClassMetadataBuilder has the following methods with a fluent inte
- ``addNamedQuery($name, $dqlQuery)``
- ``setJoinedTableInheritance()``
- ``setSingleTableInheritance()``
- ``setDiscriminatorColumn($name, $type = 'string', $length = 255, $columnDefinition = null, $enumType = null)``
- ``setDiscriminatorColumn($name, $type = 'string', $length = 255, $columnDefinition = null, $enumType = null, $options = [])``
- ``addDiscriminatorMapClass($name, $class)``
- ``setChangeTrackingPolicyDeferredExplicit()``
- ``setChangeTrackingPolicyNotify()``

View File

@@ -153,7 +153,7 @@ You need to create a class which implements ``Doctrine\ORM\Mapping\TypedFieldMap
final class CustomEnumTypedFieldMapper implements TypedFieldMapper
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function validateAndComplete(array $mapping, ReflectionProperty $field): array
{

View File

@@ -718,6 +718,7 @@ methods:
* ``andX($arg1, $arg2, ...)``
* ``orX($arg1, $arg2, ...)``
* ``not($expression)``
* ``eq($field, $value)``
* ``gt($field, $value)``
* ``lt($field, $value)``

View File

@@ -22,5 +22,5 @@ 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 spinned off a subproject, Doctrine CodeGenerator, that will fill this gap and
We spun off a subproject, Doctrine CodeGenerator, that will fill this gap and
allow you to do *Database First* development.

View File

@@ -322,7 +322,7 @@ data in your storage, and later in your application when the data is loaded agai
.. note::
This method, although very common, is inappropriate for Domain Driven
Design (`DDD <https://en.wikipedia.org/wiki/Domain-driven_design>`)
Design (`DDD <https://en.wikipedia.org/wiki/Domain-driven_design>`_)
where methods should represent real business operations and not simple
property change, And business invariants should be maintained both in the
application state (entities in this case) and in the database, with no
@@ -449,7 +449,7 @@ entity.
.. note::
A `DTO <https://en.wikipedia.org/wiki/Data_transfer_object>` is an object
A `DTO <https://en.wikipedia.org/wiki/Data_transfer_object>`_ is an object
that only carries data without any logic. Its only goal is to be transferred
from one service to another.
A ``DTO`` often represents data sent by a client and that has to be validated,

View File

@@ -302,7 +302,7 @@
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" default="string" />
<xs:attribute name="type" type="orm:type" default="string" />
<xs:attribute name="column" type="orm:columntoken" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:attribute name="unique" type="xs:boolean" default="false" />
@@ -330,6 +330,7 @@
<xs:complexType name="discriminator-column">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="options" type="orm:options" minOccurs="0" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
@@ -414,7 +415,7 @@
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" />
<xs:attribute name="type" type="orm:type" />
<xs:attribute name="column" type="orm:columntoken" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:attribute name="association-key" type="xs:boolean" default="false" />
@@ -446,6 +447,13 @@
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="type" id="type">
<xs:restriction base="xs:token">
<xs:pattern value="([a-zA-Z_u01-uff][a-zA-Z0-9_u01-uff]+)|(\c+)" id="type.class.pattern">
</xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="inverse-join-columns">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="join-column" type="orm:join-column" minOccurs="1" maxOccurs="unbounded" />
@@ -630,7 +638,7 @@
<xs:element name="options" type="orm:options" minOccurs="0" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="type" type="xs:NMTOKEN" default="string" />
<xs:attribute name="type" type="orm:type" default="string" />
<xs:attribute name="column" type="orm:columntoken" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:attribute name="unique" type="xs:boolean" default="false" />

View File

@@ -14,6 +14,8 @@ use Doctrine\ORM\Persisters\Entity\EntityPersister;
/**
* Contract for building second level cache regions components.
*
* @psalm-import-type AssociationMapping from ClassMetadata
*/
interface CacheFactory
{
@@ -31,7 +33,7 @@ interface CacheFactory
/**
* Build a collection persister for the given relation mapping.
*
* @param mixed[] $mapping The association mapping.
* @param AssociationMapping $mapping The association mapping.
*
* @return CachedCollectionPersister
*/

View File

@@ -48,7 +48,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getEntityCacheRegion($className)
{
@@ -63,7 +63,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getCollectionCacheRegion($className, $association)
{
@@ -78,7 +78,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function containsEntity($className, $identifier)
{
@@ -93,7 +93,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evictEntity($className, $identifier)
{
@@ -108,7 +108,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evictEntityRegion($className)
{
@@ -123,7 +123,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evictEntityRegions()
{
@@ -141,7 +141,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function containsCollection($className, $association, $ownerIdentifier)
{
@@ -156,7 +156,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evictCollection($className, $association, $ownerIdentifier)
{
@@ -171,7 +171,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evictCollectionRegion($className, $association)
{
@@ -186,7 +186,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evictCollectionRegions()
{
@@ -210,7 +210,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function containsQuery($regionName)
{
@@ -218,7 +218,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evictQueryRegion($regionName = null)
{
@@ -234,7 +234,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evictQueryRegions()
{
@@ -246,7 +246,7 @@ class DefaultCache implements Cache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getQueryCache($regionName = null)
{

View File

@@ -106,7 +106,7 @@ class DefaultCacheFactory implements CacheFactory
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function buildCachedEntityPersister(EntityManagerInterface $em, EntityPersister $persister, ClassMetadata $metadata)
{
@@ -134,10 +134,11 @@ class DefaultCacheFactory implements CacheFactory
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function buildCachedCollectionPersister(EntityManagerInterface $em, CollectionPersister $persister, array $mapping)
{
assert(isset($mapping['cache']));
$usage = $mapping['cache']['usage'];
$region = $this->getRegion($mapping['cache']);
@@ -161,7 +162,7 @@ class DefaultCacheFactory implements CacheFactory
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function buildQueryCache(EntityManagerInterface $em, $regionName = null)
{
@@ -177,7 +178,7 @@ class DefaultCacheFactory implements CacheFactory
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping)
{
@@ -185,7 +186,7 @@ class DefaultCacheFactory implements CacheFactory
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata)
{
@@ -193,7 +194,7 @@ class DefaultCacheFactory implements CacheFactory
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getRegion(array $cache)
{
@@ -224,7 +225,7 @@ class DefaultCacheFactory implements CacheFactory
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getTimestampRegion()
{
@@ -239,7 +240,7 @@ class DefaultCacheFactory implements CacheFactory
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function createCache(EntityManagerInterface $entityManager)
{

View File

@@ -35,7 +35,7 @@ class DefaultCollectionHydrator implements CollectionHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function buildCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, $collection)
{
@@ -49,7 +49,7 @@ class DefaultCollectionHydrator implements CollectionHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, CollectionCacheEntry $entry, PersistentCollection $collection)
{

View File

@@ -47,7 +47,7 @@ class DefaultEntityHydrator implements EntityHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity)
{
@@ -140,7 +140,7 @@ class DefaultEntityHydrator implements EntityHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, $entity = null)
{

View File

@@ -29,6 +29,8 @@ use function reset;
/**
* Default query cache implementation.
*
* @psalm-import-type AssociationMapping from ClassMetadata
*/
class DefaultQueryCache implements QueryCache
{
@@ -66,7 +68,7 @@ class DefaultQueryCache implements QueryCache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function get(QueryCacheKey $key, ResultSetMapping $rsm, array $hints = [])
{
@@ -225,7 +227,7 @@ class DefaultQueryCache implements QueryCache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function put(QueryCacheKey $key, ResultSetMapping $rsm, $result, array $hints = [])
{
@@ -326,8 +328,8 @@ class DefaultQueryCache implements QueryCache
}
/**
* @param array<string,mixed> $assoc
* @param mixed $assocValue
* @param AssociationMapping $assoc
* @param mixed $assocValue
*
* @return mixed[]|null
* @psalm-return array{targetEntity: class-string, type: mixed, list?: array[], identifier?: array}|null
@@ -448,7 +450,7 @@ class DefaultQueryCache implements QueryCache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function clear()
{
@@ -456,7 +458,7 @@ class DefaultQueryCache implements QueryCache
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getRegion()
{

View File

@@ -40,7 +40,7 @@ class CacheLoggerChain implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function collectionCacheHit($regionName, CollectionCacheKey $key)
{
@@ -50,7 +50,7 @@ class CacheLoggerChain implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function collectionCacheMiss($regionName, CollectionCacheKey $key)
{
@@ -60,7 +60,7 @@ class CacheLoggerChain implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function collectionCachePut($regionName, CollectionCacheKey $key)
{
@@ -70,7 +70,7 @@ class CacheLoggerChain implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function entityCacheHit($regionName, EntityCacheKey $key)
{
@@ -80,7 +80,7 @@ class CacheLoggerChain implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function entityCacheMiss($regionName, EntityCacheKey $key)
{
@@ -90,7 +90,7 @@ class CacheLoggerChain implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function entityCachePut($regionName, EntityCacheKey $key)
{
@@ -100,7 +100,7 @@ class CacheLoggerChain implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function queryCacheHit($regionName, QueryCacheKey $key)
{
@@ -110,7 +110,7 @@ class CacheLoggerChain implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function queryCacheMiss($regionName, QueryCacheKey $key)
{
@@ -120,7 +120,7 @@ class CacheLoggerChain implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function queryCachePut($regionName, QueryCacheKey $key)
{

View File

@@ -25,7 +25,7 @@ class StatisticsCacheLogger implements CacheLogger
private $cachePutCountMap = [];
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function collectionCacheMiss($regionName, CollectionCacheKey $key)
{
@@ -34,7 +34,7 @@ class StatisticsCacheLogger implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function collectionCacheHit($regionName, CollectionCacheKey $key)
{
@@ -43,7 +43,7 @@ class StatisticsCacheLogger implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function collectionCachePut($regionName, CollectionCacheKey $key)
{
@@ -52,7 +52,7 @@ class StatisticsCacheLogger implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function entityCacheMiss($regionName, EntityCacheKey $key)
{
@@ -61,7 +61,7 @@ class StatisticsCacheLogger implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function entityCacheHit($regionName, EntityCacheKey $key)
{
@@ -70,7 +70,7 @@ class StatisticsCacheLogger implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function entityCachePut($regionName, EntityCacheKey $key)
{
@@ -79,7 +79,7 @@ class StatisticsCacheLogger implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function queryCacheHit($regionName, QueryCacheKey $key)
{
@@ -88,7 +88,7 @@ class StatisticsCacheLogger implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function queryCacheMiss($regionName, QueryCacheKey $key)
{
@@ -97,7 +97,7 @@ class StatisticsCacheLogger implements CacheLogger
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function queryCachePut($regionName, QueryCacheKey $key)
{

View File

@@ -25,6 +25,7 @@ use function array_values;
use function assert;
use function count;
/** @psalm-import-type AssociationMapping from ClassMetadata */
abstract class AbstractCollectionPersister implements CachedCollectionPersister
{
/** @var UnitOfWork */
@@ -64,7 +65,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
* @param CollectionPersister $persister The collection persister that will be cached.
* @param Region $region The collection region.
* @param EntityManagerInterface $em The entity manager.
* @param mixed[] $association The association mapping.
* @param AssociationMapping $association The association mapping.
*/
public function __construct(CollectionPersister $persister, Region $region, EntityManagerInterface $em, array $association)
{
@@ -85,7 +86,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getCacheRegion()
{
@@ -93,7 +94,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getSourceEntityMetadata()
{
@@ -101,7 +102,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getTargetEntityMetadata()
{
@@ -109,7 +110,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadCollectionCache(PersistentCollection $collection, CollectionCacheKey $key)
{
@@ -123,7 +124,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function storeCollectionCache(CollectionCacheKey $key, $elements)
{
@@ -167,7 +168,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function contains(PersistentCollection $collection, $element)
{
@@ -175,7 +176,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function containsKey(PersistentCollection $collection, $key)
{
@@ -183,7 +184,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function count(PersistentCollection $collection)
{
@@ -199,7 +200,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function get(PersistentCollection $collection, $index)
{
@@ -207,7 +208,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function slice(PersistentCollection $collection, $offset, $length = null)
{

View File

@@ -12,7 +12,7 @@ use function spl_object_id;
class NonStrictReadWriteCachedCollectionPersister extends AbstractCollectionPersister
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function afterTransactionComplete()
{
@@ -32,7 +32,7 @@ class NonStrictReadWriteCachedCollectionPersister extends AbstractCollectionPers
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function afterTransactionRolledBack()
{
@@ -40,7 +40,7 @@ class NonStrictReadWriteCachedCollectionPersister extends AbstractCollectionPers
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function delete(PersistentCollection $collection)
{
@@ -53,7 +53,7 @@ class NonStrictReadWriteCachedCollectionPersister extends AbstractCollectionPers
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update(PersistentCollection $collection)
{

View File

@@ -11,7 +11,7 @@ use Doctrine\ORM\PersistentCollection;
class ReadOnlyCachedCollectionPersister extends NonStrictReadWriteCachedCollectionPersister
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update(PersistentCollection $collection)
{

View File

@@ -7,21 +7,23 @@ namespace Doctrine\ORM\Cache\Persister\Collection;
use Doctrine\ORM\Cache\CollectionCacheKey;
use Doctrine\ORM\Cache\ConcurrentRegion;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
use function spl_object_id;
/** @psalm-import-type AssociationMapping from ClassMetadata */
class ReadWriteCachedCollectionPersister extends AbstractCollectionPersister
{
/** @param mixed[] $association The association mapping. */
/** @param AssociationMapping $association The association mapping. */
public function __construct(CollectionPersister $persister, ConcurrentRegion $region, EntityManagerInterface $em, array $association)
{
parent::__construct($persister, $region, $em, $association);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function afterTransactionComplete()
{
@@ -41,7 +43,7 @@ class ReadWriteCachedCollectionPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function afterTransactionRolledBack()
{
@@ -61,7 +63,7 @@ class ReadWriteCachedCollectionPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function delete(PersistentCollection $collection)
{
@@ -82,7 +84,7 @@ class ReadWriteCachedCollectionPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update(PersistentCollection $collection)
{

View File

@@ -98,7 +98,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function addInsert($entity)
{
@@ -106,7 +106,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getInserts()
{
@@ -114,7 +114,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, ?array $orderBy = null)
{
@@ -130,7 +130,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getInsertSQL()
{
@@ -138,7 +138,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getResultSetMapping()
{
@@ -146,7 +146,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getSelectConditionStatementSQL($field, $value, $assoc = null, $comparison = null)
{
@@ -154,7 +154,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function exists($entity, ?Criteria $extraConditions = null)
{
@@ -170,7 +170,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getCacheRegion()
{
@@ -184,7 +184,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function storeEntityCache($entity, EntityCacheKey $key)
{
@@ -262,7 +262,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function expandParameters($criteria)
{
@@ -270,7 +270,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function expandCriteriaParameters(Criteria $criteria)
{
@@ -278,7 +278,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getClassMetadata()
{
@@ -286,7 +286,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
@@ -294,7 +294,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
@@ -302,7 +302,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getOwningTable($fieldName)
{
@@ -310,7 +310,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function executeInserts()
{
@@ -320,7 +320,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function load(array $criteria, $entity = null, $assoc = null, array $hints = [], $lockMode = null, $limit = null, ?array $orderBy = null)
{
@@ -364,7 +364,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadAll(array $criteria = [], ?array $orderBy = null, $limit = null, $offset = null)
{
@@ -400,7 +400,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadById(array $identifier, $entity = null)
{
@@ -464,7 +464,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadCriteria(Criteria $criteria)
{
@@ -503,7 +503,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $collection)
{
@@ -538,7 +538,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $collection)
{
@@ -573,7 +573,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = [])
{
@@ -581,7 +581,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function lock(array $criteria, $lockMode)
{
@@ -589,7 +589,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function refresh(array $id, $entity, $lockMode = null)
{

View File

@@ -14,7 +14,7 @@ use function get_class;
class NonStrictReadWriteCachedEntityPersister extends AbstractEntityPersister
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function afterTransactionComplete()
{
@@ -48,7 +48,7 @@ class NonStrictReadWriteCachedEntityPersister extends AbstractEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function afterTransactionRolledBack()
{
@@ -56,7 +56,7 @@ class NonStrictReadWriteCachedEntityPersister extends AbstractEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function delete($entity)
{
@@ -73,7 +73,7 @@ class NonStrictReadWriteCachedEntityPersister extends AbstractEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update($entity)
{

View File

@@ -13,7 +13,7 @@ use Doctrine\ORM\Cache\Exception\CannotUpdateReadOnlyEntity;
class ReadOnlyCachedEntityPersister extends NonStrictReadWriteCachedEntityPersister
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update($entity)
{

View File

@@ -21,7 +21,7 @@ class ReadWriteCachedEntityPersister extends AbstractEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function afterTransactionComplete()
{
@@ -51,7 +51,7 @@ class ReadWriteCachedEntityPersister extends AbstractEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function afterTransactionRolledBack()
{
@@ -71,7 +71,7 @@ class ReadWriteCachedEntityPersister extends AbstractEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function delete($entity)
{
@@ -96,7 +96,7 @@ class ReadWriteCachedEntityPersister extends AbstractEntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update($entity)
{

View File

@@ -91,7 +91,7 @@ class DefaultRegion implements Region
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getName()
{
@@ -109,7 +109,7 @@ class DefaultRegion implements Region
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function contains(CacheKey $key)
{
@@ -117,7 +117,7 @@ class DefaultRegion implements Region
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function get(CacheKey $key)
{
@@ -132,7 +132,7 @@ class DefaultRegion implements Region
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getMultiple(CollectionCacheEntry $collection)
{
@@ -164,7 +164,7 @@ class DefaultRegion implements Region
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @return bool
*/
@@ -182,7 +182,7 @@ class DefaultRegion implements Region
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @return bool
*/
@@ -192,7 +192,7 @@ class DefaultRegion implements Region
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @return bool
*/

View File

@@ -116,7 +116,7 @@ class FileLockRegion implements ConcurrentRegion
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getName()
{
@@ -124,7 +124,7 @@ class FileLockRegion implements ConcurrentRegion
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function contains(CacheKey $key)
{
@@ -136,7 +136,7 @@ class FileLockRegion implements ConcurrentRegion
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function get(CacheKey $key)
{
@@ -148,7 +148,7 @@ class FileLockRegion implements ConcurrentRegion
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getMultiple(CollectionCacheEntry $collection)
{
@@ -160,7 +160,7 @@ class FileLockRegion implements ConcurrentRegion
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function put(CacheKey $key, CacheEntry $entry, ?Lock $lock = null)
{
@@ -172,7 +172,7 @@ class FileLockRegion implements ConcurrentRegion
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evict(CacheKey $key)
{
@@ -184,7 +184,7 @@ class FileLockRegion implements ConcurrentRegion
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function evictAll()
{
@@ -202,7 +202,7 @@ class FileLockRegion implements ConcurrentRegion
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function lock(CacheKey $key)
{
@@ -223,7 +223,7 @@ class FileLockRegion implements ConcurrentRegion
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function unlock(CacheKey $key, Lock $lock)
{

View File

@@ -14,7 +14,7 @@ use Doctrine\ORM\Cache\TimestampRegion;
class UpdateTimestampCache extends DefaultRegion implements TimestampRegion
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update(CacheKey $key)
{

View File

@@ -17,7 +17,7 @@ class TimestampQueryCacheValidator implements QueryCacheValidator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function isValid(QueryCacheKey $key, QueryCacheEntry $entry)
{

View File

@@ -31,7 +31,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getConnection()
{
@@ -39,7 +39,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getExpressionBuilder()
{
@@ -47,7 +47,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @psalm-param class-string<T> $className
*
@@ -61,7 +61,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getClassMetadata($className)
{
@@ -69,7 +69,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function beginTransaction()
{
@@ -77,7 +77,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function transactional($func)
{
@@ -85,7 +85,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function wrapInTransaction(callable $func)
{
@@ -102,7 +102,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function commit()
{
@@ -110,7 +110,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function rollback()
{
@@ -118,7 +118,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function createQuery($dql = '')
{
@@ -126,7 +126,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function createNamedQuery($name)
{
@@ -134,7 +134,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function createNativeQuery($sql, ResultSetMapping $rsm)
{
@@ -142,7 +142,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function createNamedNativeQuery($name)
{
@@ -150,7 +150,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function createQueryBuilder()
{
@@ -158,7 +158,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getReference($entityName, $id)
{
@@ -166,7 +166,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getPartialReference($entityName, $identifier)
{
@@ -174,7 +174,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function close()
{
@@ -182,7 +182,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function copy($entity, $deep = false)
{
@@ -190,7 +190,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function lock($entity, $lockMode, $lockVersion = null)
{
@@ -198,7 +198,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function find($className, $id, $lockMode = null, $lockVersion = null)
{
@@ -206,7 +206,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function flush($entity = null)
{
@@ -214,7 +214,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function refresh($object)
{
@@ -228,7 +228,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getEventManager()
{
@@ -236,7 +236,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getConfiguration()
{
@@ -244,7 +244,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function isOpen()
{
@@ -252,7 +252,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getUnitOfWork()
{
@@ -260,7 +260,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getHydrator($hydrationMode)
{
@@ -268,7 +268,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function newHydrator($hydrationMode)
{
@@ -276,7 +276,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getProxyFactory()
{
@@ -284,7 +284,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getFilters()
{
@@ -292,7 +292,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function isFiltersStateClean()
{
@@ -300,7 +300,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function hasFilters()
{
@@ -308,7 +308,7 @@ abstract class EntityManagerDecorator extends ObjectManagerDecorator implements
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getCache()
{

View File

@@ -27,7 +27,7 @@ use Doctrine\Persistence\ObjectManager;
interface EntityManagerInterface extends ObjectManager
{
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @psalm-param class-string<T> $className
*

View File

@@ -297,7 +297,7 @@ class EntityRepository implements ObjectRepository, Selectable
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getClassName()
{

View File

@@ -17,7 +17,7 @@ class AssignedGenerator extends AbstractIdGenerator
/**
* Returns the identifier assigned to the given entity.
*
* {@inheritdoc}
* {@inheritDoc}
*
* @throws EntityMissingAssignedId
*/

View File

@@ -49,7 +49,7 @@ class IdentityGenerator extends AbstractIdGenerator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function isPostInsertGenerator()
{

View File

@@ -21,20 +21,20 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
*
* @var int
*/
private $_allocationSize;
private $allocationSize;
/**
* The name of the sequence.
*
* @var string
*/
private $_sequenceName;
private $sequenceName;
/** @var int */
private $_nextValue = 0;
private $nextValue = 0;
/** @var int|null */
private $_maxValue = null;
private $maxValue = null;
/**
* Initializes a new sequence generator.
@@ -44,8 +44,8 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
*/
public function __construct($sequenceName, $allocationSize)
{
$this->_sequenceName = $sequenceName;
$this->_allocationSize = $allocationSize;
$this->sequenceName = $sequenceName;
$this->allocationSize = $allocationSize;
}
/**
@@ -53,20 +53,20 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
*/
public function generateId(EntityManagerInterface $em, $entity)
{
if ($this->_maxValue === null || $this->_nextValue === $this->_maxValue) {
if ($this->maxValue === null || $this->nextValue === $this->maxValue) {
// Allocate new values
$connection = $em->getConnection();
$sql = $connection->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName);
$sql = $connection->getDatabasePlatform()->getSequenceNextValSQL($this->sequenceName);
if ($connection instanceof PrimaryReadReplicaConnection) {
$connection->ensureConnectedToPrimary();
}
$this->_nextValue = (int) $connection->fetchOne($sql);
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
$this->nextValue = (int) $connection->fetchOne($sql);
$this->maxValue = $this->nextValue + $this->allocationSize;
}
return $this->_nextValue++;
return $this->nextValue++;
}
/**
@@ -76,7 +76,7 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
*/
public function getCurrentMaxValue()
{
return $this->_maxValue;
return $this->maxValue;
}
/**
@@ -86,7 +86,7 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
*/
public function getNextValue()
{
return $this->_nextValue;
return $this->nextValue;
}
/**
@@ -103,8 +103,8 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
public function __serialize(): array
{
return [
'allocationSize' => $this->_allocationSize,
'sequenceName' => $this->_sequenceName,
'allocationSize' => $this->allocationSize,
'sequenceName' => $this->sequenceName,
];
}
@@ -123,7 +123,7 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
/** @param array<string, mixed> $data */
public function __unserialize(array $data): void
{
$this->_sequenceName = $data['sequenceName'];
$this->_allocationSize = $data['allocationSize'];
$this->sequenceName = $data['sequenceName'];
$this->allocationSize = $data['allocationSize'];
}
}

View File

@@ -14,19 +14,19 @@ use Doctrine\ORM\EntityManagerInterface;
class TableGenerator extends AbstractIdGenerator
{
/** @var string */
private $_tableName;
private $tableName;
/** @var string */
private $_sequenceName;
private $sequenceName;
/** @var int */
private $_allocationSize;
private $allocationSize;
/** @var int|null */
private $_nextValue;
private $nextValue;
/** @var int|null */
private $_maxValue;
private $maxValue;
/**
* @param string $tableName
@@ -35,9 +35,9 @@ class TableGenerator extends AbstractIdGenerator
*/
public function __construct($tableName, $sequenceName = 'default', $allocationSize = 10)
{
$this->_tableName = $tableName;
$this->_sequenceName = $sequenceName;
$this->_allocationSize = $allocationSize;
$this->tableName = $tableName;
$this->sequenceName = $sequenceName;
$this->allocationSize = $allocationSize;
}
/**
@@ -47,23 +47,23 @@ class TableGenerator extends AbstractIdGenerator
EntityManagerInterface $em,
$entity
) {
if ($this->_maxValue === null || $this->_nextValue === $this->_maxValue) {
if ($this->maxValue === null || $this->nextValue === $this->maxValue) {
// Allocate new values
$conn = $em->getConnection();
if ($conn->getTransactionNestingLevel() === 0) {
// use select for update
$sql = $conn->getDatabasePlatform()->getTableHiLoCurrentValSql($this->_tableName, $this->_sequenceName);
$sql = $conn->getDatabasePlatform()->getTableHiLoCurrentValSql($this->tableName, $this->sequenceName);
$currentLevel = $conn->fetchOne($sql);
if ($currentLevel !== null) {
$this->_nextValue = $currentLevel;
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
$this->nextValue = $currentLevel;
$this->maxValue = $this->nextValue + $this->allocationSize;
$updateSql = $conn->getDatabasePlatform()->getTableHiLoUpdateNextValSql(
$this->_tableName,
$this->_sequenceName,
$this->_allocationSize
$this->tableName,
$this->sequenceName,
$this->allocationSize
);
if ($conn->executeStatement($updateSql, [1 => $currentLevel, 2 => $currentLevel + 1]) !== 1) {
@@ -78,6 +78,6 @@ class TableGenerator extends AbstractIdGenerator
}
}
return $this->_nextValue++;
return $this->nextValue++;
}
}

View File

@@ -19,39 +19,39 @@ use function reset;
class ArrayHydrator extends AbstractHydrator
{
/** @var array<string,bool> */
private $_rootAliases = [];
private $rootAliases = [];
/** @var bool */
private $_isSimpleQuery = false;
private $isSimpleQuery = false;
/** @var mixed[] */
private $_identifierMap = [];
private $identifierMap = [];
/** @var mixed[] */
private $_resultPointers = [];
private $resultPointers = [];
/** @var array<string,string> */
private $_idTemplate = [];
private $idTemplate = [];
/** @var int */
private $_resultCounter = 0;
private $resultCounter = 0;
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function prepare()
{
$this->_isSimpleQuery = count($this->resultSetMapping()->aliasMap) <= 1;
$this->isSimpleQuery = count($this->resultSetMapping()->aliasMap) <= 1;
foreach ($this->resultSetMapping()->aliasMap as $dqlAlias => $className) {
$this->_identifierMap[$dqlAlias] = [];
$this->_resultPointers[$dqlAlias] = [];
$this->_idTemplate[$dqlAlias] = '';
$this->identifierMap[$dqlAlias] = [];
$this->resultPointers[$dqlAlias] = [];
$this->idTemplate[$dqlAlias] = '';
}
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function hydrateAllData()
{
@@ -65,12 +65,12 @@ class ArrayHydrator extends AbstractHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function hydrateRowData(array $row, array &$result)
{
// 1) Initialize
$id = $this->_idTemplate; // initialize the id-memory
$id = $this->idTemplate; // initialize the id-memory
$nonemptyComponents = [];
$rowData = $this->gatherRowData($row, $id, $nonemptyComponents);
@@ -91,14 +91,14 @@ class ArrayHydrator extends AbstractHydrator
// Get a reference to the right element in the result tree.
// This element will get the associated element attached.
if ($this->resultSetMapping()->isMixed && isset($this->_rootAliases[$parent])) {
$first = reset($this->_resultPointers);
if ($this->resultSetMapping()->isMixed && isset($this->rootAliases[$parent])) {
$first = reset($this->resultPointers);
// TODO: Exception if $key === null ?
$baseElement =& $this->_resultPointers[$parent][key($first)];
} elseif (isset($this->_resultPointers[$parent])) {
$baseElement =& $this->_resultPointers[$parent];
$baseElement =& $this->resultPointers[$parent][key($first)];
} elseif (isset($this->resultPointers[$parent])) {
$baseElement =& $this->resultPointers[$parent];
} else {
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
unset($this->resultPointers[$dqlAlias]); // Ticket #1228
continue;
}
@@ -116,8 +116,8 @@ class ArrayHydrator extends AbstractHydrator
}
if (isset($nonemptyComponents[$dqlAlias])) {
$indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
$index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
$indexExists = isset($this->identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
$index = $indexExists ? $this->identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
$indexIsValid = $index !== false ? isset($baseElement[$relationAlias][$index]) : false;
if (! $indexExists || ! $indexIsValid) {
@@ -131,7 +131,7 @@ class ArrayHydrator extends AbstractHydrator
end($baseElement[$relationAlias]);
$this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = key($baseElement[$relationAlias]);
$this->identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = key($baseElement[$relationAlias]);
}
}
} else {
@@ -155,8 +155,8 @@ class ArrayHydrator extends AbstractHydrator
} else {
// It's a root result element
$this->_rootAliases[$dqlAlias] = true; // Mark as root
$entityKey = $this->resultSetMapping()->entityMappings[$dqlAlias] ?: 0;
$this->rootAliases[$dqlAlias] = true; // Mark as root
$entityKey = $this->resultSetMapping()->entityMappings[$dqlAlias] ?: 0;
// if this row has a NULL value for the root result id then make it a null result.
if (! isset($nonemptyComponents[$dqlAlias])) {
@@ -164,14 +164,14 @@ class ArrayHydrator extends AbstractHydrator
? [$entityKey => null]
: null;
$resultKey = $this->_resultCounter;
++$this->_resultCounter;
$resultKey = $this->resultCounter;
++$this->resultCounter;
continue;
}
// Check for an existing element
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
if ($this->isSimpleQuery || ! isset($this->identifierMap[$dqlAlias][$id[$dqlAlias]])) {
$element = $this->resultSetMapping()->isMixed
? [$entityKey => $data]
: $data;
@@ -180,15 +180,15 @@ class ArrayHydrator extends AbstractHydrator
$resultKey = $row[$this->resultSetMapping()->indexByMap[$dqlAlias]];
$result[$resultKey] = $element;
} else {
$resultKey = $this->_resultCounter;
$resultKey = $this->resultCounter;
$result[] = $element;
++$this->_resultCounter;
++$this->resultCounter;
}
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey;
$this->identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey;
} else {
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
$index = $this->identifierMap[$dqlAlias][$id[$dqlAlias]];
$resultKey = $index;
}
@@ -197,7 +197,7 @@ class ArrayHydrator extends AbstractHydrator
}
if (! isset($resultKey)) {
$this->_resultCounter++;
$this->resultCounter++;
}
// Append scalar values to mixed result sets
@@ -206,7 +206,7 @@ class ArrayHydrator extends AbstractHydrator
// this only ever happens when no object is fetched (scalar result only)
$resultKey = isset($this->resultSetMapping()->indexByMap['scalars'])
? $row[$this->resultSetMapping()->indexByMap['scalars']]
: $this->_resultCounter - 1;
: $this->resultCounter - 1;
}
foreach ($rowData['scalars'] as $name => $value) {
@@ -217,7 +217,7 @@ class ArrayHydrator extends AbstractHydrator
// Append new object to mixed result sets
if (isset($rowData['newObjects'])) {
if (! isset($resultKey)) {
$resultKey = $this->_resultCounter - 1;
$resultKey = $this->resultCounter - 1;
}
$scalarCount = (isset($rowData['scalars']) ? count($rowData['scalars']) : 0);
@@ -253,19 +253,19 @@ class ArrayHydrator extends AbstractHydrator
bool $oneToOne
): void {
if ($coll === null) {
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
unset($this->resultPointers[$dqlAlias]); // Ticket #1228
return;
}
if ($oneToOne) {
$this->_resultPointers[$dqlAlias] =& $coll;
$this->resultPointers[$dqlAlias] =& $coll;
return;
}
if ($index !== false) {
$this->_resultPointers[$dqlAlias] =& $coll[$index];
$this->resultPointers[$dqlAlias] =& $coll[$index];
return;
}
@@ -275,6 +275,6 @@ class ArrayHydrator extends AbstractHydrator
}
end($coll);
$this->_resultPointers[$dqlAlias] =& $coll[key($coll)];
$this->resultPointers[$dqlAlias] =& $coll[key($coll)];
}
}

View File

@@ -16,21 +16,21 @@ use ReturnTypeWillChange;
class IterableResult implements Iterator
{
/** @var AbstractHydrator */
private $_hydrator;
private $hydrator;
/** @var bool */
private $_rewinded = false;
private $rewinded = false;
/** @var int */
private $_key = -1;
private $key = -1;
/** @var mixed[]|null */
private $_current = null;
private $current = null;
/** @param AbstractHydrator $hydrator */
public function __construct($hydrator)
{
$this->_hydrator = $hydrator;
$this->hydrator = $hydrator;
}
/**
@@ -41,12 +41,12 @@ class IterableResult implements Iterator
#[ReturnTypeWillChange]
public function rewind()
{
if ($this->_rewinded === true) {
if ($this->rewinded === true) {
throw new HydrationException('Can only iterate a Result once.');
}
$this->_current = $this->next();
$this->_rewinded = true;
$this->current = $this->next();
$this->rewinded = true;
}
/**
@@ -57,30 +57,30 @@ class IterableResult implements Iterator
#[ReturnTypeWillChange]
public function next()
{
$this->_current = $this->_hydrator->hydrateRow();
$this->_key++;
$this->current = $this->hydrator->hydrateRow();
$this->key++;
return $this->_current;
return $this->current;
}
/** @return mixed */
#[ReturnTypeWillChange]
public function current()
{
return $this->_current;
return $this->current;
}
/** @return int */
#[ReturnTypeWillChange]
public function key()
{
return $this->_key;
return $this->key;
}
/** @return bool */
#[ReturnTypeWillChange]
public function valid()
{
return $this->_current !== false;
return $this->current !== false;
}
}

View File

@@ -14,6 +14,7 @@ use Doctrine\Persistence\Proxy;
use function array_fill_keys;
use function array_keys;
use function array_map;
use function count;
use function is_array;
use function key;
@@ -52,7 +53,7 @@ class ObjectHydrator extends AbstractHydrator
private $existingCollections = [];
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function prepare()
{
@@ -108,7 +109,7 @@ class ObjectHydrator extends AbstractHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function cleanup()
{
@@ -139,7 +140,7 @@ class ObjectHydrator extends AbstractHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function hydrateAllData()
{
@@ -284,13 +285,17 @@ class ObjectHydrator extends AbstractHydrator
$class = $this->_metadataCache[$className];
if ($class->isIdentifierComposite) {
$idHash = '';
foreach ($class->identifier as $fieldName) {
$idHash .= ' ' . (isset($class->associationMappings[$fieldName])
? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']]
: $data[$fieldName]);
}
$idHash = UnitOfWork::getIdHashByIdentifier(
array_map(
/** @return mixed */
static function (string $fieldName) use ($data, $class) {
return isset($class->associationMappings[$fieldName])
? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']]
: $data[$fieldName];
},
$class->identifier
)
);
return $this->_uow->tryGetByIdHash(ltrim($idHash), $class->rootEntityName);
} elseif (isset($class->associationMappings[$class->identifier[0]])) {

View File

@@ -16,7 +16,7 @@ use function count;
final class ScalarColumnHydrator extends AbstractHydrator
{
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @throws MultipleSelectorsFoundException
* @throws Exception

View File

@@ -12,7 +12,7 @@ namespace Doctrine\ORM\Internal\Hydration;
class ScalarHydrator extends AbstractHydrator
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function hydrateAllData()
{
@@ -26,7 +26,7 @@ class ScalarHydrator extends AbstractHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function hydrateRowData(array $row, array &$result)
{

View File

@@ -28,7 +28,7 @@ class SimpleObjectHydrator extends AbstractHydrator
private $class;
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function prepare()
{
@@ -44,7 +44,7 @@ class SimpleObjectHydrator extends AbstractHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function cleanup()
{
@@ -55,7 +55,7 @@ class SimpleObjectHydrator extends AbstractHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function hydrateAllData()
{
@@ -71,7 +71,7 @@ class SimpleObjectHydrator extends AbstractHydrator
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function hydrateRowData(array $row, array &$result)
{

View File

@@ -17,7 +17,7 @@ use function key;
class SingleScalarHydrator extends AbstractHydrator
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function hydrateAllData()
{

View File

@@ -51,7 +51,7 @@ final class HydrationCompleteHandler
}
/**
* This method should me called after any hydration cycle completed.
* This method should be called after any hydration cycle completed.
*
* Method fires all deferred invocations of postLoad events
*/

View File

@@ -16,7 +16,7 @@ class AnsiQuoteStrategy implements QuoteStrategy
use SQLResultCasing;
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -24,7 +24,7 @@ class AnsiQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getTableName(ClassMetadata $class, AbstractPlatform $platform)
{
@@ -32,7 +32,7 @@ class AnsiQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -40,7 +40,7 @@ class AnsiQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -48,7 +48,7 @@ class AnsiQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -56,7 +56,7 @@ class AnsiQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -64,7 +64,7 @@ class AnsiQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform)
{
@@ -72,7 +72,7 @@ class AnsiQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ?ClassMetadata $class = null)
{

View File

@@ -220,10 +220,11 @@ class ClassMetadataBuilder
* @param string $type
* @param int $length
* @psalm-param class-string<BackedEnum>|null $enumType
* @psalm-param array<string, mixed> $options
*
* @return $this
*/
public function setDiscriminatorColumn($name, $type = 'string', $length = 255, ?string $columnDefinition = null, ?string $enumType = null)
public function setDiscriminatorColumn($name, $type = 'string', $length = 255, ?string $columnDefinition = null, ?string $enumType = null, array $options = [])
{
$this->cm->setDiscriminatorColumn(
[
@@ -232,6 +233,7 @@ class ClassMetadataBuilder
'length' => $length,
'columnDefinition' => $columnDefinition,
'enumType' => $enumType,
'options' => $options,
]
);

View File

@@ -20,7 +20,7 @@ final class ChainTypedFieldMapper implements TypedFieldMapper
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function validateAndComplete(array $mapping, ReflectionProperty $field): array
{

View File

@@ -4,12 +4,102 @@ declare(strict_types=1);
namespace Doctrine\ORM\Mapping;
use BackedEnum;
/**
* {@inheritDoc}
*
* @todo remove or rename ClassMetadataInfo to ClassMetadata
* @template-covariant T of object
* @template-extends ClassMetadataInfo<T>
* @psalm-type FieldMapping = array{
* type: string,
* fieldName: string,
* columnName: string,
* length?: int,
* id?: bool,
* nullable?: bool,
* notInsertable?: bool,
* notUpdatable?: bool,
* generated?: int,
* enumType?: class-string<BackedEnum>,
* columnDefinition?: string,
* precision?: int,
* scale?: int,
* unique?: bool,
* inherited?: class-string,
* originalClass?: class-string,
* originalField?: string,
* quoted?: bool,
* requireSQLConversion?: bool,
* declared?: class-string,
* declaredField?: string,
* options?: array<string, mixed>,
* version?: string,
* default?: string|int,
* }
* @psalm-type JoinColumnData = array{
* name: string,
* referencedColumnName: string,
* unique?: bool,
* quoted?: bool,
* fieldName?: string,
* onDelete?: string,
* columnDefinition?: string,
* nullable?: bool,
* }
* @psalm-type AssociationMapping = array{
* cache?: array,
* cascade: array<string>,
* declared?: class-string,
* fetch: mixed,
* fieldName: string,
* id?: bool,
* inherited?: class-string,
* indexBy?: string,
* inversedBy: string|null,
* isCascadeRemove: bool,
* isCascadePersist: bool,
* isCascadeRefresh: bool,
* isCascadeMerge: bool,
* isCascadeDetach: bool,
* isOnDeleteCascade?: bool,
* isOwningSide: bool,
* joinColumns?: array<JoinColumnData>,
* joinColumnFieldNames?: array<string, string>,
* joinTable?: array,
* joinTableColumns?: list<mixed>,
* mappedBy: string|null,
* orderBy?: array,
* originalClass?: class-string,
* originalField?: string,
* orphanRemoval?: bool,
* relationToSourceKeyColumns?: array,
* relationToTargetKeyColumns?: array,
* sourceEntity: class-string,
* sourceToTargetKeyColumns?: array<string, string>,
* targetEntity: class-string,
* targetToSourceKeyColumns?: array<string, string>,
* type: int,
* unique?: bool,
* }
* @psalm-type DiscriminatorColumnMapping = array{
* name: string,
* fieldName: string,
* type: string,
* length?: int,
* columnDefinition?: string|null,
* enumType?: class-string<BackedEnum>|null,
* options?: array<string, mixed>,
* }
* @psalm-type EmbeddedClassMapping = array{
* class: class-string,
* columnPrefix: string|null,
* declaredField: string|null,
* originalField: string|null,
* inherited?: class-string,
* declared?: class-string,
* }
*/
class ClassMetadata extends ClassMetadataInfo
{

View File

@@ -47,6 +47,9 @@ use function substr;
* to a relational database.
*
* @extends AbstractClassMetadataFactory<ClassMetadata>
* @psalm-import-type AssociationMapping from ClassMetadata
* @psalm-import-type EmbeddedClassMapping from ClassMetadata
* @psalm-import-type FieldMapping from ClassMetadata
*/
class ClassMetadataFactory extends AbstractClassMetadataFactory
{
@@ -145,15 +148,21 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
}
if (! $class->isMappedSuperclass) {
if ($rootEntityFound && $class->isInheritanceTypeNone()) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/10431',
"Entity class '%s' is a subclass of the root entity class '%s', but no inheritance mapping type was declared. This is a misconfiguration and will be an error in Doctrine ORM 3.0.",
$class->name,
end($nonSuperclassParents)
);
}
foreach ($class->embeddedClasses as $property => $embeddableClass) {
if (isset($embeddableClass['inherited'])) {
continue;
}
if (! (isset($embeddableClass['class']) && $embeddableClass['class'])) {
throw MappingException::missingEmbeddedClass($property);
}
if (isset($this->embeddablesActiveNesting[$embeddableClass['class']])) {
throw MappingException::infiniteEmbeddableNesting($class->name, $property);
}
@@ -411,20 +420,30 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
return strtolower(end($parts));
}
/**
* Puts the `inherited` and `declared` values into mapping information for fields, associations
* and embedded classes.
*
* @param AssociationMapping|EmbeddedClassMapping|FieldMapping $mapping
*/
private function addMappingInheritanceInformation(array &$mapping, ClassMetadata $parentClass): void
{
if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
$mapping['inherited'] = $parentClass->name;
}
if (! isset($mapping['declared'])) {
$mapping['declared'] = $parentClass->name;
}
}
/**
* Adds inherited fields to the subclass mapping.
*/
private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass): void
{
foreach ($parentClass->fieldMappings as $mapping) {
if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
$mapping['inherited'] = $parentClass->name;
}
if (! isset($mapping['declared'])) {
$mapping['declared'] = $parentClass->name;
}
$this->addMappingInheritanceInformation($mapping, $parentClass);
$subClass->addInheritedFieldMapping($mapping);
}
@@ -441,14 +460,7 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass): void
{
foreach ($parentClass->associationMappings as $field => $mapping) {
if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
$mapping['inherited'] = $parentClass->name;
}
if (! isset($mapping['declared'])) {
$mapping['declared'] = $parentClass->name;
}
$this->addMappingInheritanceInformation($mapping, $parentClass);
// When the class inheriting the relation ($subClass) is the first entity class since the
// relation has been defined in a mapped superclass (or in a chain
// of mapped superclasses) above, then declare this current entity class as the source of
@@ -456,10 +468,6 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
// According to the definitions given in https://github.com/doctrine/orm/pull/10396/,
// this is the case <=> ! isset($mapping['inherited']).
if (! isset($mapping['inherited'])) {
if ($mapping['type'] & ClassMetadata::TO_MANY && ! $mapping['isOwningSide']) {
throw MappingException::illegalToManyAssociationOnMappedSuperclass($parentClass->name, $field);
}
$mapping['sourceEntity'] = $subClass->name;
}
@@ -470,14 +478,7 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
private function addInheritedEmbeddedClasses(ClassMetadata $subClass, ClassMetadata $parentClass): void
{
foreach ($parentClass->embeddedClasses as $field => $embeddedClass) {
if (! isset($embeddedClass['inherited']) && ! $parentClass->isMappedSuperclass) {
$embeddedClass['inherited'] = $parentClass->name;
}
if (! isset($embeddedClass['declared'])) {
$embeddedClass['declared'] = $parentClass->name;
}
$this->addMappingInheritanceInformation($embeddedClass, $parentClass);
$subClass->embeddedClasses[$field] = $embeddedClass;
}
}

View File

@@ -68,83 +68,11 @@ use const PHP_VERSION_ID;
*
* @template-covariant T of object
* @template-implements ClassMetadata<T>
* @psalm-type FieldMapping = array{
* type: string,
* fieldName: string,
* columnName: string,
* length?: int,
* id?: bool,
* nullable?: bool,
* notInsertable?: bool,
* notUpdatable?: bool,
* generated?: int,
* enumType?: class-string<BackedEnum>,
* columnDefinition?: string,
* precision?: int,
* scale?: int,
* unique?: bool,
* inherited?: class-string,
* originalClass?: class-string,
* originalField?: string,
* quoted?: bool,
* requireSQLConversion?: bool,
* declared?: class-string,
* declaredField?: string,
* options?: array<string, mixed>
* }
* @psalm-type JoinColumnData = array{
* name: string,
* referencedColumnName: string,
* unique?: bool,
* quoted?: bool,
* fieldName?: string,
* onDelete?: string,
* columnDefinition?: string,
* nullable?: bool,
* }
* @psalm-type AssociationMapping = array{
* cache?: array,
* cascade: array<string>,
* declared?: class-string,
* fetch: mixed,
* fieldName: string,
* id?: bool,
* inherited?: class-string,
* indexBy?: string,
* inversedBy: string|null,
* isCascadeRemove: bool,
* isCascadePersist: bool,
* isCascadeRefresh: bool,
* isCascadeMerge: bool,
* isCascadeDetach: bool,
* isOnDeleteCascade?: bool,
* isOwningSide: bool,
* joinColumns?: array<JoinColumnData>,
* joinColumnFieldNames?: array<string, string>,
* joinTable?: array,
* joinTableColumns?: list<mixed>,
* mappedBy: string|null,
* orderBy?: array,
* originalClass?: class-string,
* originalField?: string,
* orphanRemoval?: bool,
* relationToSourceKeyColumns?: array,
* relationToTargetKeyColumns?: array,
* sourceEntity: class-string,
* sourceToTargetKeyColumns?: array<string, string>,
* targetEntity: class-string,
* targetToSourceKeyColumns?: array<string, string>,
* type: int,
* unique?: bool,
* }
* @psalm-type DiscriminatorColumnMapping = array{
* name: string,
* fieldName: string,
* type: string,
* length?: int,
* columnDefinition?: string|null,
* enumType?: class-string<BackedEnum>|null,
* }
* @psalm-import-type AssociationMapping from \Doctrine\ORM\Mapping\ClassMetadata
* @psalm-import-type FieldMapping from \Doctrine\ORM\Mapping\ClassMetadata
* @psalm-import-type EmbeddedClassMapping from \Doctrine\ORM\Mapping\ClassMetadata
* @psalm-import-type JoinColumnData from \Doctrine\ORM\Mapping\ClassMetadata
* @psalm-import-type DiscriminatorColumnMapping from \Doctrine\ORM\Mapping\ClassMetadata
*/
class ClassMetadataInfo implements ClassMetadata
{
@@ -170,6 +98,8 @@ class ClassMetadataInfo implements ClassMetadata
/**
* TABLE_PER_CLASS means the class will be persisted according to the rules
* of <tt>Concrete Table Inheritance</tt>.
*
* @deprecated
*/
public const INHERITANCE_TYPE_TABLE_PER_CLASS = 4;
@@ -390,7 +320,8 @@ class ClassMetadataInfo implements ClassMetadata
public $isEmbeddedClass = false;
/**
* READ-ONLY: The names of the parent classes (ancestors).
* READ-ONLY: The names of the parent <em>entity</em> classes (ancestors), starting with the
* nearest one and ending with the root entity class.
*
* @psalm-var list<class-string>
*/
@@ -442,7 +373,7 @@ class ClassMetadataInfo implements ClassMetadata
* declared in another parent <em>entity or mapped superclass</em>. The value is the FQCN
* of the topmost non-transient class that contains mapping information for this field.
*
* @psalm-var array<string, mixed[]>
* @psalm-var array<string, EmbeddedClassMapping>
*/
public $embeddedClasses = [];
@@ -1166,6 +1097,7 @@ class ClassMetadataInfo implements ClassMetadata
foreach ($this->embeddedClasses as $property => $embeddedClass) {
if (isset($embeddedClass['declaredField'])) {
assert($embeddedClass['originalField'] !== null);
$childProperty = $this->getAccessibleProperty(
$reflService,
$this->embeddedClasses[$embeddedClass['declaredField']]['class'],
@@ -1651,9 +1583,9 @@ class ClassMetadataInfo implements ClassMetadata
/**
* Validates & completes the given field mapping based on typed property.
*
* @param array{fieldName: string, type?: mixed} $mapping The field mapping to validate & complete.
* @param array{fieldName: string, type?: string} $mapping The field mapping to validate & complete.
*
* @return array{fieldName: string, enumType?: string, type?: mixed} The updated mapping.
* @return array{fieldName: string, enumType?: class-string<BackedEnum>, type?: string} The updated mapping.
*/
private function validateAndCompleteTypedFieldMapping(array $mapping): array
{
@@ -1697,7 +1629,7 @@ class ClassMetadataInfo implements ClassMetadata
* enumType?: class-string,
* } $mapping The field mapping to validate & complete.
*
* @return mixed[] The updated mapping.
* @return FieldMapping The updated mapping.
*
* @throws MappingException
*/
@@ -1923,30 +1855,7 @@ class ClassMetadataInfo implements ClassMetadata
* @psalm-param array<string, mixed> $mapping The mapping to validate & complete.
*
* @return mixed[] The validated & completed mapping.
* @psalm-return array{
* mappedBy: mixed|null,
* inversedBy: mixed|null,
* isOwningSide: bool,
* sourceEntity: class-string,
* targetEntity: string,
* fieldName: mixed,
* fetch: mixed,
* cascade: array<string>,
* isCascadeRemove: bool,
* isCascadePersist: bool,
* isCascadeRefresh: bool,
* isCascadeMerge: bool,
* isCascadeDetach: bool,
* type: int,
* originalField: string,
* originalClass: class-string,
* joinColumns?: array{0: array{name: string, referencedColumnName: string}}|mixed,
* id?: mixed,
* sourceToTargetKeyColumns?: array<string, string>,
* joinColumnFieldNames?: array<string, string>,
* targetToSourceKeyColumns?: array<string, string>,
* orphanRemoval: bool
* }
* @psalm-return AssociationMapping
*
* @throws RuntimeException
* @throws MappingException
@@ -1955,6 +1864,14 @@ class ClassMetadataInfo implements ClassMetadata
{
$mapping = $this->_validateAndCompleteAssociationMapping($mapping);
if (isset($mapping['joinColumns']) && $mapping['joinColumns'] && ! $mapping['isOwningSide']) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/10654',
'JoinColumn configuration is not allowed on the inverse side of one-to-one associations, and will throw a MappingException in Doctrine ORM 3.0'
);
}
if (isset($mapping['joinColumns']) && $mapping['joinColumns']) {
$mapping['isOwningSide'] = true;
}
@@ -2036,22 +1953,7 @@ class ClassMetadataInfo implements ClassMetadata
* @psalm-param array<string, mixed> $mapping The mapping to validate and complete.
*
* @return mixed[] The validated and completed mapping.
* @psalm-return array{
* mappedBy: mixed,
* inversedBy: mixed,
* isOwningSide: bool,
* sourceEntity: string,
* targetEntity: string,
* fieldName: mixed,
* fetch: int|mixed,
* cascade: array<array-key,string>,
* isCascadeRemove: bool,
* isCascadePersist: bool,
* isCascadeRefresh: bool,
* isCascadeMerge: bool,
* isCascadeDetach: bool,
* orphanRemoval: bool
* }
* @psalm-return AssociationMapping
*
* @throws MappingException
* @throws InvalidArgumentException
@@ -2079,30 +1981,7 @@ class ClassMetadataInfo implements ClassMetadata
* @psalm-param array<string, mixed> $mapping The mapping to validate & complete.
*
* @return mixed[] The validated & completed mapping.
* @psalm-return array{
* mappedBy: mixed,
* inversedBy: mixed,
* isOwningSide: bool,
* sourceEntity: class-string,
* targetEntity: string,
* fieldName: mixed,
* fetch: mixed,
* cascade: array<string>,
* isCascadeRemove: bool,
* isCascadePersist: bool,
* isCascadeRefresh: bool,
* isCascadeMerge: bool,
* isCascadeDetach: bool,
* type: int,
* originalField: string,
* originalClass: class-string,
* joinTable?: array{inverseJoinColumns: mixed}|mixed,
* joinTableColumns?: list<mixed>,
* isOnDeleteCascade?: true,
* relationToSourceKeyColumns?: array,
* relationToTargetKeyColumns?: array,
* orphanRemoval: bool
* }
* @psalm-return AssociationMapping
*
* @throws InvalidArgumentException
*/
@@ -2375,11 +2254,19 @@ class ClassMetadataInfo implements ClassMetadata
/**
* Checks whether the mapped class uses the TABLE_PER_CLASS inheritance mapping strategy.
*
* @deprecated
*
* @return bool TRUE if the class participates in a TABLE_PER_CLASS inheritance mapping,
* FALSE otherwise.
*/
public function isInheritanceTypeTablePerClass()
{
Deprecation::triggerIfCalledFromOutside(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/10414/',
'Concrete table inheritance has never been implemented, and its stubs will be removed in Doctrine ORM 3.0 with no replacement'
);
return $this->inheritanceType === self::INHERITANCE_TYPE_TABLE_PER_CLASS;
}
@@ -2531,7 +2418,8 @@ class ClassMetadataInfo implements ClassMetadata
}
/**
* Sets the parent class names.
* Sets the parent class names. Only <em>entity</em> classes may be given.
*
* Assumes that the class names in the passed array are in the order:
* directParent -> directParentParent -> directParentParentParent ... -> root.
*
@@ -2585,12 +2473,16 @@ class ClassMetadataInfo implements ClassMetadata
$mapping = $this->associationMappings[$fieldName];
//if (isset($mapping['inherited']) && (count($overrideMapping) !== 1 || ! isset($overrideMapping['fetch']))) {
// TODO: Deprecate overriding the fetch mode via association override for 3.0,
// users should do this with a listener and a custom attribute/annotation
// TODO: Enable this exception in 2.8
//throw MappingException::illegalOverrideOfInheritedProperty($this->name, $fieldName);
//}
if (isset($mapping['inherited'])) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/10470',
'Overrides are only allowed for fields or associations declared in mapped superclasses or traits. This is not the case for %s::%s, which was inherited from %s. This is a misconfiguration and will be an error in Doctrine ORM 3.0.',
$this->name,
$fieldName,
$mapping['inherited']
);
}
if (isset($overrideMapping['joinColumns'])) {
$mapping['joinColumns'] = $overrideMapping['joinColumns'];
@@ -2650,10 +2542,17 @@ class ClassMetadataInfo implements ClassMetadata
$mapping = $this->fieldMappings[$fieldName];
//if (isset($mapping['inherited'])) {
// TODO: Enable this exception in 2.8
if (isset($mapping['inherited'])) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/10470',
'Overrides are only allowed for fields or associations declared in mapped superclasses or traits. This is not the case for %s::%s, which was inherited from %s. This is a misconfiguration and will be an error in Doctrine ORM 3.0.',
$this->name,
$fieldName,
$mapping['inherited']
);
//throw MappingException::illegalOverrideOfInheritedProperty($this->name, $fieldName);
//}
}
if (isset($mapping['id'])) {
$overrideMapping['id'] = $mapping['id'];
@@ -2796,6 +2695,14 @@ class ClassMetadataInfo implements ClassMetadata
*/
private function isInheritanceType(int $type): bool
{
if ($type === self::INHERITANCE_TYPE_TABLE_PER_CLASS) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/10414/',
'Concrete table inheritance has never been implemented, and its stubs will be removed in Doctrine ORM 3.0 with no replacement'
);
}
return $type === self::INHERITANCE_TYPE_NONE ||
$type === self::INHERITANCE_TYPE_SINGLE_TABLE ||
$type === self::INHERITANCE_TYPE_JOINED ||
@@ -2848,7 +2755,7 @@ class ClassMetadataInfo implements ClassMetadata
* Adds a field mapping without completing/validating it.
* This is mainly used to add inherited field mappings to derived classes.
*
* @psalm-param array<string, mixed> $fieldMapping
* @psalm-param FieldMapping $fieldMapping
*
* @return void
*/
@@ -3084,7 +2991,7 @@ class ClassMetadataInfo implements ClassMetadata
/**
* Stores the association mapping.
*
* @psalm-param array<string, mixed> $assocMapping
* @psalm-param AssociationMapping $assocMapping
*
* @return void
*
@@ -3236,7 +3143,7 @@ class ClassMetadataInfo implements ClassMetadata
* @see getDiscriminatorColumn()
*
* @param mixed[]|null $columnDef
* @psalm-param array{name: string|null, fieldName?: string, type?: string, length?: int, columnDefinition?: string|null, enumType?: class-string<BackedEnum>|null}|null $columnDef
* @psalm-param array{name: string|null, fieldName?: string, type?: string, length?: int, columnDefinition?: string|null, enumType?: class-string<BackedEnum>|null, options?: array<string, mixed>}|null $columnDef
*
* @return void
*
@@ -3841,8 +3748,16 @@ class ClassMetadataInfo implements ClassMetadata
}
}
if (! (isset($mapping['class']) && $mapping['class'])) {
throw MappingException::missingEmbeddedClass($mapping['fieldName']);
}
$fqcn = $this->fullyQualifiedClassName($mapping['class']);
assert($fqcn !== null);
$this->embeddedClasses[$mapping['fieldName']] = [
'class' => $this->fullyQualifiedClassName($mapping['class']),
'class' => $fqcn,
'columnPrefix' => $mapping['columnPrefix'] ?? null,
'declaredField' => $mapping['declaredField'] ?? null,
'originalField' => $mapping['originalField'] ?? null,
@@ -3934,7 +3849,7 @@ class ClassMetadataInfo implements ClassMetadata
return $sequencePrefix;
}
/** @psalm-param array<string, mixed> $mapping */
/** @psalm-param AssociationMapping $mapping */
private function assertMappingOrderBy(array $mapping): void
{
if (isset($mapping['orderBy']) && ! is_array($mapping['orderBy'])) {
@@ -3947,7 +3862,14 @@ class ClassMetadataInfo implements ClassMetadata
{
$reflectionProperty = $reflService->getAccessibleProperty($class, $field);
if ($reflectionProperty !== null && PHP_VERSION_ID >= 80100 && $reflectionProperty->isReadOnly()) {
$reflectionProperty = new ReflectionReadonlyProperty($reflectionProperty);
$declaringClass = $reflectionProperty->getDeclaringClass()->name;
if ($declaringClass !== $class) {
$reflectionProperty = $reflService->getAccessibleProperty($declaringClass, $field);
}
if ($reflectionProperty !== null) {
$reflectionProperty = new ReflectionReadonlyProperty($reflectionProperty);
}
}
return $reflectionProperty;

View File

@@ -21,7 +21,7 @@ class DefaultEntityListenerResolver implements EntityListenerResolver
private $instances = [];
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function clear($className = null)
{
@@ -38,7 +38,7 @@ class DefaultEntityListenerResolver implements EntityListenerResolver
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function register($object)
{
@@ -50,7 +50,7 @@ class DefaultEntityListenerResolver implements EntityListenerResolver
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function resolve($className)
{

View File

@@ -17,7 +17,7 @@ use function substr;
class DefaultNamingStrategy implements NamingStrategy
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function classToTableName($className)
{
@@ -29,7 +29,7 @@ class DefaultNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function propertyToColumnName($propertyName, $className = null)
{
@@ -37,7 +37,7 @@ class DefaultNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null)
{
@@ -45,7 +45,7 @@ class DefaultNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function referenceColumnName()
{
@@ -53,7 +53,7 @@ class DefaultNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @param string $propertyName
* @param class-string $className
@@ -64,7 +64,7 @@ class DefaultNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function joinTableName($sourceEntity, $targetEntity, $propertyName = null)
{
@@ -73,7 +73,7 @@ class DefaultNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function joinKeyColumnName($entityName, $referencedColumnName = null)
{

View File

@@ -21,7 +21,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
use SQLResultCasing;
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -31,7 +31,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @todo Table names should be computed in DBAL depending on the platform
*/
@@ -53,7 +53,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -63,7 +63,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -73,7 +73,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -83,7 +83,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform)
{
@@ -104,7 +104,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform)
{
@@ -135,7 +135,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ?ClassMetadata $class = null)
{

View File

@@ -43,7 +43,7 @@ final class DefaultTypedFieldMapper implements TypedFieldMapper
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function validateAndComplete(array $mapping, ReflectionProperty $field): array
{

View File

@@ -45,18 +45,29 @@ final class DiscriminatorColumn implements MappingAttribute
*/
public $enumType = null;
/** @param class-string<\BackedEnum>|null $enumType */
/**
* @var array<string, mixed>
* @readonly
*/
public $options = [];
/**
* @param class-string<\BackedEnum>|null $enumType
* @param array<string, mixed> $options
*/
public function __construct(
?string $name = null,
?string $type = null,
?int $length = null,
?string $columnDefinition = null,
?string $enumType = null
?string $enumType = null,
array $options = []
) {
$this->name = $name;
$this->type = $type;
$this->length = $length;
$this->columnDefinition = $columnDefinition;
$this->enumType = $enumType;
$this->options = $options;
}
}

View File

@@ -313,15 +313,19 @@ class AnnotationDriver extends CompatibilityAnnotationDriver
$discrColumnAnnot = $classAnnotations[Mapping\DiscriminatorColumn::class];
assert($discrColumnAnnot instanceof Mapping\DiscriminatorColumn);
$metadata->setDiscriminatorColumn(
[
'name' => $discrColumnAnnot->name,
'type' => $discrColumnAnnot->type ?: 'string',
'length' => $discrColumnAnnot->length ?? 255,
'columnDefinition' => $discrColumnAnnot->columnDefinition,
'enumType' => $discrColumnAnnot->enumType,
]
);
$columnDef = [
'name' => $discrColumnAnnot->name,
'type' => $discrColumnAnnot->type ?: 'string',
'length' => $discrColumnAnnot->length ?? 255,
'columnDefinition' => $discrColumnAnnot->columnDefinition,
'enumType' => $discrColumnAnnot->enumType,
];
if ($discrColumnAnnot->options) {
$columnDef['options'] = $discrColumnAnnot->options;
}
$metadata->setDiscriminatorColumn($columnDef);
} else {
$metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]);
}

View File

@@ -265,15 +265,19 @@ class AttributeDriver extends CompatibilityAnnotationDriver
if (isset($classAttributes[Mapping\DiscriminatorColumn::class])) {
$discrColumnAttribute = $classAttributes[Mapping\DiscriminatorColumn::class];
$metadata->setDiscriminatorColumn(
[
'name' => isset($discrColumnAttribute->name) ? (string) $discrColumnAttribute->name : null,
'type' => isset($discrColumnAttribute->type) ? (string) $discrColumnAttribute->type : 'string',
'length' => isset($discrColumnAttribute->length) ? (int) $discrColumnAttribute->length : 255,
'columnDefinition' => isset($discrColumnAttribute->columnDefinition) ? (string) $discrColumnAttribute->columnDefinition : null,
'enumType' => isset($discrColumnAttribute->enumType) ? (string) $discrColumnAttribute->enumType : null,
]
);
$columnDef = [
'name' => isset($discrColumnAttribute->name) ? (string) $discrColumnAttribute->name : null,
'type' => isset($discrColumnAttribute->type) ? (string) $discrColumnAttribute->type : 'string',
'length' => isset($discrColumnAttribute->length) ? (int) $discrColumnAttribute->length : 255,
'columnDefinition' => isset($discrColumnAttribute->columnDefinition) ? (string) $discrColumnAttribute->columnDefinition : null,
'enumType' => isset($discrColumnAttribute->enumType) ? (string) $discrColumnAttribute->enumType : null,
];
if ($discrColumnAttribute->options) {
$columnDef['options'] = (array) $discrColumnAttribute->options;
}
$metadata->setDiscriminatorColumn($columnDef);
} else {
$metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]);
}
@@ -433,6 +437,14 @@ class AttributeDriver extends CompatibilityAnnotationDriver
if ($joinTableAttribute->options) {
$joinTable['options'] = $joinTableAttribute->options;
}
foreach ($joinTableAttribute->joinColumns as $joinColumn) {
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
}
foreach ($joinTableAttribute->inverseJoinColumns as $joinColumn) {
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
}
}
foreach ($this->reader->getPropertyAttributeCollection($property, Mapping\JoinColumn::class) as $joinColumn) {

View File

@@ -61,7 +61,7 @@ class DatabaseDriver implements MappingDriver
private const JSON_ARRAY = 'json_array';
/** @var AbstractSchemaManager */
private $_sm;
private $sm;
/** @var array<string,Table>|null */
private $tables = null;
@@ -90,7 +90,7 @@ class DatabaseDriver implements MappingDriver
public function __construct(AbstractSchemaManager $schemaManager)
{
$this->_sm = $schemaManager;
$this->sm = $schemaManager;
$this->inflector = InflectorFactory::create()->build();
}
@@ -294,7 +294,7 @@ class DatabaseDriver implements MappingDriver
$this->tables = $this->manyToManyTables = $this->classToTableNames = [];
foreach ($this->_sm->listTables() as $table) {
foreach ($this->sm->listTables() as $table) {
$tableName = $table->getName();
$foreignKeys = $table->getForeignKeys();

View File

@@ -204,15 +204,19 @@ class XmlDriver extends FileDriver
// Evaluate <discriminator-column...>
if (isset($xmlRoot->{'discriminator-column'})) {
$discrColumn = $xmlRoot->{'discriminator-column'};
$metadata->setDiscriminatorColumn(
[
'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null,
'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string',
'length' => isset($discrColumn['length']) ? (int) $discrColumn['length'] : 255,
'columnDefinition' => isset($discrColumn['column-definition']) ? (string) $discrColumn['column-definition'] : null,
'enumType' => isset($discrColumn['enum-type']) ? (string) $discrColumn['enum-type'] : null,
]
);
$columnDef = [
'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null,
'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string',
'length' => isset($discrColumn['length']) ? (int) $discrColumn['length'] : 255,
'columnDefinition' => isset($discrColumn['column-definition']) ? (string) $discrColumn['column-definition'] : null,
'enumType' => isset($discrColumn['enum-type']) ? (string) $discrColumn['enum-type'] : null,
];
if (isset($discrColumn['options'])) {
$columnDef['options'] = $this->parseOptions($discrColumn['options']->children());
}
$metadata->setDiscriminatorColumn($columnDef);
} else {
$metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]);
}
@@ -985,6 +989,7 @@ class XmlDriver extends FileDriver
$result = [];
// Note: we do not use `simplexml_load_file()` because of https://bugs.php.net/bug.php?id=62577
$xmlElement = simplexml_load_string(file_get_contents($file));
assert($xmlElement !== false);
if (isset($xmlElement->entity)) {
foreach ($xmlElement->entity as $entityElement) {

View File

@@ -6,6 +6,7 @@ namespace Doctrine\ORM\Mapping;
use Attribute;
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
use Doctrine\Deprecations\Deprecation;
/**
* @Annotation
@@ -28,6 +29,14 @@ final class InheritanceType implements MappingAttribute
/** @psalm-param 'NONE'|'JOINED'|'SINGLE_TABLE'|'TABLE_PER_CLASS' $value */
public function __construct(string $value)
{
if ($value === 'TABLE_PER_CLASS') {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/10414/',
'Concrete table inheritance has never been implemented, and its stubs will be removed in Doctrine ORM 3.0 with no replacement'
);
}
$this->value = $value;
}
}

View File

@@ -33,7 +33,7 @@ class MappingException extends ORMException
}
/**
* @param string $entityName
* @param class-string $entityName
*
* @return MappingException
*/
@@ -346,7 +346,7 @@ class MappingException extends ORMException
}
/**
* @param string $className
* @param class-string $className
*
* @return MappingException
*/
@@ -908,8 +908,7 @@ class MappingException extends ORMException
{
return new self(
sprintf(
'Override for %s::%s is only allowed for attributes/associations ' .
'declared on a mapped superclass or a trait.',
'Overrides are only allowed for fields or associations declared in mapped superclasses or traits, which is not the case for %s::%s.',
$className,
$propertyName
)

View File

@@ -8,6 +8,9 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* A set of rules for determining the column, alias and table quotes.
*
* @psalm-import-type AssociationMapping from ClassMetadata
* @psalm-import-type JoinColumnData from ClassMetadata
*/
interface QuoteStrategy
{
@@ -39,7 +42,7 @@ interface QuoteStrategy
/**
* Gets the (possibly quoted) name of the join table.
*
* @param mixed[] $association
* @param AssociationMapping $association
*
* @return string
*/
@@ -48,7 +51,7 @@ interface QuoteStrategy
/**
* Gets the (possibly quoted) join column name.
*
* @param mixed[] $joinColumn
* @param JoinColumnData $joinColumn
*
* @return string
*/
@@ -57,7 +60,7 @@ interface QuoteStrategy
/**
* Gets the (possibly quoted) join column name.
*
* @param mixed[] $joinColumn
* @param JoinColumnData $joinColumn
*
* @return string
*/

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Doctrine\ORM\Mapping;
use BackedEnum;
use ReflectionProperty;
interface TypedFieldMapper
@@ -11,9 +12,9 @@ interface TypedFieldMapper
/**
* Validates & completes the given field mapping based on typed property.
*
* @param array{fieldName: string, enumType?: string, type?: mixed} $mapping The field mapping to validate & complete.
* @param array{fieldName: string, enumType?: class-string<BackedEnum>, type?: string} $mapping The field mapping to validate & complete.
*
* @return array{fieldName: string, enumType?: string, type?: mixed} The updated mapping.
* @return array{fieldName: string, enumType?: class-string<BackedEnum>, type?: string} The updated mapping.
*/
public function validateAndComplete(array $mapping, ReflectionProperty $field): array;
}

View File

@@ -73,7 +73,7 @@ class UnderscoreNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function classToTableName($className)
{
@@ -85,7 +85,7 @@ class UnderscoreNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function propertyToColumnName($propertyName, $className = null)
{
@@ -93,7 +93,7 @@ class UnderscoreNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null)
{
@@ -101,7 +101,7 @@ class UnderscoreNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function referenceColumnName()
{
@@ -109,7 +109,7 @@ class UnderscoreNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @param string $propertyName
* @param class-string $className
@@ -120,7 +120,7 @@ class UnderscoreNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function joinTableName($sourceEntity, $targetEntity, $propertyName = null)
{
@@ -128,7 +128,7 @@ class UnderscoreNamingStrategy implements NamingStrategy
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function joinKeyColumnName($entityName, $referencedColumnName = null)
{

View File

@@ -40,7 +40,7 @@ final class NativeQuery extends AbstractQuery
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function _doExecute()
{

View File

@@ -22,6 +22,8 @@ use function sprintf;
/**
* Contains exception messages for all invalid lifecycle state exceptions inside UnitOfWork
*
* @psalm-import-type AssociationMapping from ClassMetadata
*/
class ORMInvalidArgumentException extends InvalidArgumentException
{
@@ -80,8 +82,8 @@ class ORMInvalidArgumentException extends InvalidArgumentException
}
/**
* @param array[][]|object[][] $newEntitiesWithAssociations non-empty an array
* of [array $associationMapping, object $entity] pairs
* @psalm-param non-empty-list<array{AssociationMapping, object}> $newEntitiesWithAssociations non-empty an array
* of [array $associationMapping, object $entity] pairs
*
* @return ORMInvalidArgumentException
*/
@@ -109,7 +111,7 @@ class ORMInvalidArgumentException extends InvalidArgumentException
/**
* @param object $entry
* @psalm-param array<string, string> $associationMapping
* @psalm-param AssociationMapping $associationMapping
*
* @return ORMInvalidArgumentException
*/
@@ -120,7 +122,7 @@ class ORMInvalidArgumentException extends InvalidArgumentException
/**
* @param object $entry
* @psalm-param array<string, string> $assoc
* @psalm-param AssociationMapping $assoc
*
* @return ORMInvalidArgumentException
*/
@@ -220,8 +222,8 @@ EXCEPTION
}
/**
* @param mixed[] $assoc
* @param mixed $actualValue
* @param AssociationMapping $assoc
* @param mixed $actualValue
*
* @return self
*/
@@ -271,7 +273,7 @@ EXCEPTION
/**
* @param object $entity
* @psalm-param array<string,string> $associationMapping
* @psalm-param AssociationMapping $associationMapping
*/
private static function newEntityFoundThroughRelationshipMessage(array $associationMapping, $entity): string
{

View File

@@ -12,6 +12,7 @@ use Doctrine\Common\Collections\Selectable;
use Doctrine\ORM\Mapping\ClassMetadata;
use ReturnTypeWillChange;
use RuntimeException;
use UnexpectedValueException;
use function array_combine;
use function array_diff_key;
@@ -36,6 +37,7 @@ use function spl_object_id;
* @psalm-template T
* @template-extends AbstractLazyCollection<TKey,T>
* @template-implements Selectable<TKey,T>
* @psalm-import-type AssociationMapping from ClassMetadata
*/
final class PersistentCollection extends AbstractLazyCollection implements Selectable
{
@@ -58,7 +60,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
* The association mapping the collection belongs to.
* This is currently either a OneToManyMapping or a ManyToManyMapping.
*
* @psalm-var array<string, mixed>|null
* @psalm-var AssociationMapping|null
*/
private $association;
@@ -113,7 +115,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
* describes the association between the owner and the elements of the collection.
*
* @param object $entity
* @psalm-param array<string, mixed> $assoc
* @psalm-param AssociationMapping $assoc
*/
public function setOwner($entity, array $assoc): void
{
@@ -161,7 +163,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
// If _backRefFieldName is set and its a one-to-many association,
// we need to set the back reference.
if ($this->backRefFieldName && $this->association['type'] === ClassMetadata::ONE_TO_MANY) {
if ($this->backRefFieldName && $this->getMapping()['type'] === ClassMetadata::ONE_TO_MANY) {
assert($this->typeClass !== null);
// Set back reference to owner
$this->typeClass->reflFields[$this->backRefFieldName]->setValue(
@@ -190,7 +192,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
// If _backRefFieldName is set, then the association is bidirectional
// and we need to set the back reference.
if ($this->backRefFieldName && $this->association['type'] === ClassMetadata::ONE_TO_MANY) {
if ($this->backRefFieldName && $this->getMapping()['type'] === ClassMetadata::ONE_TO_MANY) {
assert($this->typeClass !== null);
// Set back reference to owner
$this->typeClass->reflFields[$this->backRefFieldName]->setValue(
@@ -271,10 +273,14 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
/**
* INTERNAL: Gets the association mapping of the collection.
*
* @psalm-return array<string, mixed>|null
* @psalm-return AssociationMapping
*/
public function getMapping(): ?array
public function getMapping(): array
{
if ($this->association === null) {
throw new UnexpectedValueException('The underlying association mapping is null although it should not be');
}
return $this->association;
}
@@ -291,8 +297,8 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
if (
$this->association !== null &&
$this->association['isOwningSide'] &&
$this->association['type'] === ClassMetadata::MANY_TO_MANY &&
$this->getMapping()['isOwningSide'] &&
$this->getMapping()['type'] === ClassMetadata::MANY_TO_MANY &&
$this->owner &&
$this->em !== null &&
$this->em->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify()
@@ -333,7 +339,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function remove($key)
{
@@ -351,9 +357,9 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
if (
$this->association !== null &&
$this->association['type'] & ClassMetadata::TO_MANY &&
$this->getMapping()['type'] & ClassMetadata::TO_MANY &&
$this->owner &&
$this->association['orphanRemoval']
$this->getMapping()['orphanRemoval']
) {
$this->getUnitOfWork()->scheduleOrphanRemoval($removed);
}
@@ -362,7 +368,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function removeElement($element): bool
{
@@ -376,9 +382,9 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
if (
$this->association !== null &&
$this->association['type'] & ClassMetadata::TO_MANY &&
$this->getMapping()['type'] & ClassMetadata::TO_MANY &&
$this->owner &&
$this->association['orphanRemoval']
$this->getMapping()['orphanRemoval']
) {
$this->getUnitOfWork()->scheduleOrphanRemoval($element);
}
@@ -387,15 +393,15 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function containsKey($key): bool
{
if (
! $this->initialized && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY
&& isset($this->association['indexBy'])
! $this->initialized && $this->getMapping()['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY
&& isset($this->getMapping()['indexBy'])
) {
$persister = $this->getUnitOfWork()->getCollectionPersister($this->association);
$persister = $this->getUnitOfWork()->getCollectionPersister($this->getMapping());
return $this->unwrap()->containsKey($key) || $persister->containsKey($this, $key);
}
@@ -404,14 +410,14 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @template TMaybeContained
*/
public function contains($element): bool
{
if (! $this->initialized && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) {
$persister = $this->getUnitOfWork()->getCollectionPersister($this->association);
if (! $this->initialized && $this->getMapping()['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) {
$persister = $this->getUnitOfWork()->getCollectionPersister($this->getMapping());
return $this->unwrap()->contains($element) || $persister->contains($this, $element);
}
@@ -420,22 +426,22 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function get($key)
{
if (
! $this->initialized
&& $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY
&& isset($this->association['indexBy'])
&& $this->getMapping()['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY
&& isset($this->getMapping()['indexBy'])
) {
assert($this->em !== null);
assert($this->typeClass !== null);
if (! $this->typeClass->isIdentifierComposite && $this->typeClass->isIdentifier($this->association['indexBy'])) {
if (! $this->typeClass->isIdentifierComposite && $this->typeClass->isIdentifier($this->getMapping()['indexBy'])) {
return $this->em->find($this->typeClass->name, $key);
}
return $this->getUnitOfWork()->getCollectionPersister($this->association)->get($this, $key);
return $this->getUnitOfWork()->getCollectionPersister($this->getMapping())->get($this, $key);
}
return parent::get($key);
@@ -443,7 +449,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
public function count(): int
{
if (! $this->initialized && $this->association !== null && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) {
if (! $this->initialized && $this->association !== null && $this->getMapping()['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) {
$persister = $this->getUnitOfWork()->getCollectionPersister($this->association);
return $persister->count($this) + ($this->isDirty ? $this->unwrap()->count() : 0);
@@ -453,7 +459,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function set($key, $value): void
{
@@ -467,7 +473,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function add($value): bool
{
@@ -485,7 +491,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
/* ArrayAccess implementation */
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function offsetExists($offset): bool
{
@@ -493,7 +499,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
#[ReturnTypeWillChange]
public function offsetGet($offset)
@@ -502,7 +508,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function offsetSet($offset, $value): void
{
@@ -516,7 +522,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @return object|null
*/
@@ -539,11 +545,12 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
return;
}
$uow = $this->getUnitOfWork();
$uow = $this->getUnitOfWork();
$association = $this->getMapping();
if (
$this->association['type'] & ClassMetadata::TO_MANY &&
$this->association['orphanRemoval'] &&
$association['type'] & ClassMetadata::TO_MANY &&
$association['orphanRemoval'] &&
$this->owner
) {
// we need to initialize here, as orphan removal acts like implicit cascadeRemove,
@@ -559,7 +566,7 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
$this->initialized = true; // direct call, {@link initialize()} is too expensive
if ($this->association['isOwningSide'] && $this->owner) {
if ($association['isOwningSide'] && $this->owner) {
$this->changed();
$uow->scheduleCollectionDeletion($this);
@@ -598,8 +605,8 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
*/
public function slice($offset, $length = null): array
{
if (! $this->initialized && ! $this->isDirty && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) {
$persister = $this->getUnitOfWork()->getCollectionPersister($this->association);
if (! $this->initialized && ! $this->isDirty && $this->getMapping()['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) {
$persister = $this->getUnitOfWork()->getCollectionPersister($this->getMapping());
return $persister->slice($this, $offset, $length);
}
@@ -650,8 +657,9 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
return $this->unwrap()->matching($criteria);
}
if ($this->association['type'] === ClassMetadata::MANY_TO_MANY) {
$persister = $this->getUnitOfWork()->getCollectionPersister($this->association);
$association = $this->getMapping();
if ($association['type'] === ClassMetadata::MANY_TO_MANY) {
$persister = $this->getUnitOfWork()->getCollectionPersister($association);
return new ArrayCollection($persister->loadCriteria($this, $criteria));
}
@@ -663,11 +671,11 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
$criteria = clone $criteria;
$criteria->where($expression);
$criteria->orderBy($criteria->getOrderings() ?: $this->association['orderBy'] ?? []);
$criteria->orderBy($criteria->getOrderings() ?: $association['orderBy'] ?? []);
$persister = $this->getUnitOfWork()->getEntityPersister($this->association['targetEntity']);
$persister = $this->getUnitOfWork()->getEntityPersister($association['targetEntity']);
return $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY
return $association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY
? new LazyCriteriaCollection($persister, $criteria)
: new ArrayCollection($persister->loadCriteria($criteria));
}

View File

@@ -6,6 +6,7 @@ namespace Doctrine\ORM\Persisters\Collection;
use BadMethodCallException;
use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Collections\Expr\Comparison;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\PersistentCollection;
@@ -24,11 +25,13 @@ use function sprintf;
/**
* Persister for many-to-many collections.
*
* @psalm-import-type AssociationMapping from ClassMetadata
*/
class ManyToManyPersister extends AbstractCollectionPersister
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function delete(PersistentCollection $collection)
{
@@ -49,7 +52,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update(PersistentCollection $collection)
{
@@ -80,7 +83,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function get(PersistentCollection $collection, $index)
{
@@ -99,7 +102,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function count(PersistentCollection $collection)
{
@@ -169,7 +172,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function containsKey(PersistentCollection $collection, $key)
{
@@ -246,10 +249,15 @@ class ManyToManyPersister extends AbstractCollectionPersister
foreach ($parameters as $parameter) {
[$name, $value, $operator] = $parameter;
$field = $this->quoteStrategy->getColumnName($name, $targetClass, $this->platform);
$whereClauses[] = sprintf('te.%s %s ?', $field, $operator);
$params[] = $value;
$paramTypes[] = PersisterHelper::getTypeOfField($name, $targetClass, $this->em)[0];
$field = $this->quoteStrategy->getColumnName($name, $targetClass, $this->platform);
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];
}
}
$tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform);
@@ -286,7 +294,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
* JOIN.
*
* @param mixed[] $mapping Array containing mapping information.
* @psalm-param array<string, mixed> $mapping
* @psalm-param AssociationMapping $mapping
*
* @return string[] ordered tuple:
* - JOIN condition to add to the SQL
@@ -339,7 +347,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
* Generate ON condition
*
* @param mixed[] $mapping
* @psalm-param array<string, mixed> $mapping
* @psalm-param AssociationMapping $mapping
*
* @return string[]
* @psalm-return list<string>

View File

@@ -24,7 +24,7 @@ use function is_string;
class OneToManyPersister extends AbstractCollectionPersister
{
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @return int|null
*/
@@ -50,7 +50,7 @@ class OneToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update(PersistentCollection $collection)
{
@@ -61,7 +61,7 @@ class OneToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function get(PersistentCollection $collection, $index)
{
@@ -87,7 +87,7 @@ class OneToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function count(PersistentCollection $collection)
{
@@ -103,7 +103,7 @@ class OneToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function slice(PersistentCollection $collection, $offset, $length = null)
{
@@ -114,7 +114,7 @@ class OneToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function containsKey(PersistentCollection $collection, $key)
{
@@ -138,7 +138,7 @@ class OneToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function contains(PersistentCollection $collection, $element)
{
@@ -158,7 +158,7 @@ class OneToManyPersister extends AbstractCollectionPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadCriteria(PersistentCollection $collection, Criteria $criteria)
{

View File

@@ -17,7 +17,7 @@ use function sprintf;
abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function prepareInsertData($entity)
{
@@ -39,7 +39,7 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
abstract protected function getDiscriminatorColumnTableName();
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
{

View File

@@ -87,6 +87,8 @@ use function trim;
*
* Subclasses can be created to provide custom persisting and querying strategies,
* i.e. spanning multiple tables.
*
* @psalm-import-type AssociationMapping from ClassMetadata
*/
class BasicEntityPersister implements EntityPersister
{
@@ -217,7 +219,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getClassMetadata()
{
@@ -225,7 +227,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getResultSetMapping()
{
@@ -233,7 +235,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function addInsert($entity)
{
@@ -241,7 +243,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getInserts()
{
@@ -249,7 +251,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function executeInserts()
{
@@ -271,6 +273,10 @@ class BasicEntityPersister implements EntityPersister
$paramIndex = 1;
foreach ($insertData[$tableName] as $column => $value) {
if ($value instanceof BackedEnum) {
$value = $value->value;
}
$stmt->bindValue($paramIndex++, $value, $this->columnTypes[$column]);
}
}
@@ -386,7 +392,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update($entity)
{
@@ -587,7 +593,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function delete($entity)
{
@@ -731,7 +737,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getOwningTable($fieldName)
{
@@ -739,7 +745,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function load(array $criteria, $entity = null, $assoc = null, array $hints = [], $lockMode = null, $limit = null, ?array $orderBy = null)
{
@@ -761,7 +767,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadById(array $identifier, $entity = null)
{
@@ -769,7 +775,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = [])
{
@@ -829,7 +835,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function refresh(array $id, $entity, $lockMode = null)
{
@@ -856,7 +862,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadCriteria(Criteria $criteria)
{
@@ -874,7 +880,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function expandCriteriaParameters(Criteria $criteria)
{
@@ -890,22 +896,24 @@ class BasicEntityPersister implements EntityPersister
$valueVisitor->dispatch($expression);
[$params, $types] = $valueVisitor->getParamsAndTypes();
foreach ($params as $param) {
$sqlParams = array_merge($sqlParams, $this->getValues($param));
}
[, $types] = $valueVisitor->getParamsAndTypes();
foreach ($types as $type) {
[$field, $value] = $type;
$sqlTypes = array_merge($sqlTypes, $this->getTypes($field, $value, $this->class));
[$field, $value, $operator] = $type;
if ($value === null && ($operator === Comparison::EQ || $operator === Comparison::NEQ)) {
continue;
}
$sqlParams = array_merge($sqlParams, $this->getValues($value));
$sqlTypes = array_merge($sqlTypes, $this->getTypes($field, $value, $this->class));
}
return [$sqlParams, $sqlTypes];
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadAll(array $criteria = [], ?array $orderBy = null, $limit = null, $offset = null)
{
@@ -921,7 +929,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
@@ -979,7 +987,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $collection)
{
@@ -1065,7 +1073,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, ?array $orderBy = null)
{
@@ -1332,9 +1340,9 @@ class BasicEntityPersister implements EntityPersister
/**
* Gets the SQL join fragment used when selecting entities from an association.
*
* @param string $field
* @param mixed[] $assoc
* @param string $alias
* @param string $field
* @param AssociationMapping $assoc
* @param string $alias
*
* @return string
*/
@@ -1366,7 +1374,7 @@ class BasicEntityPersister implements EntityPersister
* Gets the SQL join fragment used when selecting entities from a
* many-to-many association.
*
* @psalm-param array<string, mixed> $manyToMany
* @psalm-param AssociationMapping $manyToMany
*
* @return string
*/
@@ -1396,7 +1404,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getInsertSQL()
{
@@ -1546,7 +1554,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function lock(array $criteria, $lockMode)
{
@@ -1623,7 +1631,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getSelectConditionStatementSQL($field, $value, $assoc = null, $comparison = null)
{
@@ -1694,7 +1702,7 @@ class BasicEntityPersister implements EntityPersister
/**
* Builds the left-hand-side of a where condition statement.
*
* @psalm-param array<string, mixed>|null $assoc
* @psalm-param AssociationMapping|null $assoc
*
* @return string[]
* @psalm-return list<string>
@@ -1767,7 +1775,7 @@ class BasicEntityPersister implements EntityPersister
* Subclasses are supposed to override this method if they intend to change
* or alter the criteria by which entities are selected.
*
* @param mixed[]|null $assoc
* @param AssociationMapping|null $assoc
* @psalm-param array<string, mixed> $criteria
* @psalm-param array<string, mixed>|null $assoc
*
@@ -1785,7 +1793,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
@@ -1797,7 +1805,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $collection)
{
@@ -1810,7 +1818,7 @@ class BasicEntityPersister implements EntityPersister
* Builds criteria and execute SQL statement to fetch the one to many entities from.
*
* @param object $sourceEntity
* @psalm-param array<string, mixed> $assoc
* @psalm-param AssociationMapping $assoc
*/
private function getOneToManyStatement(
array $assoc,
@@ -1864,7 +1872,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function expandParameters($criteria)
{
@@ -2027,7 +2035,7 @@ class BasicEntityPersister implements EntityPersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function exists($entity, ?Criteria $extraConditions = null)
{

View File

@@ -14,6 +14,8 @@ use Doctrine\ORM\Query\ResultSetMapping;
/**
* Entity persister interface
* Define the behavior that should be implemented by all entity persisters.
*
* @psalm-import-type AssociationMapping from ClassMetadata
*/
interface EntityPersister
{
@@ -48,11 +50,11 @@ interface EntityPersister
* Gets the SELECT SQL to select one or more entities by a set of field criteria.
*
* @param mixed[]|Criteria $criteria
* @param mixed[]|null $assoc
* @param int|null $lockMode
* @param int|null $limit
* @param int|null $offset
* @param mixed[]|null $orderBy
* @psalm-param AssociationMapping|null $assoc
* @psalm-param LockMode::*|null $lockMode
*
* @return string
@@ -87,11 +89,10 @@ interface EntityPersister
/**
* Gets the SQL WHERE condition for matching a field with a given value.
*
* @param string $field
* @param mixed $value
* @param mixed[]|null $assoc
* @param string|null $comparison
* @psalm-param array<string, mixed>|null $assoc
* @param string $field
* @param mixed $value
* @param AssociationMapping|null $assoc
* @param string|null $comparison
*
* @return string
*/
@@ -171,19 +172,18 @@ interface EntityPersister
/**
* Loads an entity by a list of field criteria.
*
* @param mixed[] $criteria The criteria by which to load the entity.
* @param object|null $entity The entity to load the data into. If not specified,
* a new entity is created.
* @param mixed[]|null $assoc The association that connects the entity
* to load to another entity, if any.
* @param mixed[] $hints Hints for entity creation.
* @param int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants
* or NULL if no specific lock mode should be used
* for loading the entity.
* @param int|null $limit Limit number of results.
* @param string[]|null $orderBy Criteria to order by.
* @param mixed[] $criteria The criteria by which to load the entity.
* @param object|null $entity The entity to load the data into. If not specified,
* a new entity is created.
* @param AssociationMapping|null $assoc The association that connects the entity
* to load to another entity, if any.
* @param mixed[] $hints Hints for entity creation.
* @param int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants
* or NULL if no specific lock mode should be used
* for loading the entity.
* @param int|null $limit Limit number of results.
* @param string[]|null $orderBy Criteria to order by.
* @psalm-param array<string, mixed> $criteria
* @psalm-param array<string, mixed>|null $assoc
* @psalm-param array<string, mixed> $hints
* @psalm-param LockMode::*|null $lockMode
* @psalm-param array<string, string>|null $orderBy
@@ -222,7 +222,7 @@ interface EntityPersister
* @psalm-param array<string, mixed> $identifier The identifier of the entity to load. Must be provided if
* the association to load represents the owning side, otherwise
* the identifier is derived from the $sourceEntity.
* @psalm-param array<string, mixed> $assoc The association to load.
* @psalm-param AssociationMapping $assoc The association to load.
*
* @return object The loaded and managed entity instance or NULL if the entity can not be found.
*
@@ -269,7 +269,7 @@ interface EntityPersister
* @param object $sourceEntity
* @param int|null $offset
* @param int|null $limit
* @psalm-param array<string, mixed> $assoc
* @psalm-param AssociationMapping $assoc
*
* @return mixed[]
*/
@@ -280,7 +280,7 @@ interface EntityPersister
*
* @param object $sourceEntity The entity that owns the collection.
* @param PersistentCollection $collection The collection to fill.
* @psalm-param array<string, mixed> $assoc The association mapping of the association being loaded.
* @psalm-param AssociationMapping $assoc The association mapping of the association being loaded.
*
* @return mixed[]
*/
@@ -291,7 +291,7 @@ interface EntityPersister
*
* @param object $sourceEntity
* @param PersistentCollection $collection The collection to load/fill.
* @psalm-param array<string, mixed> $assoc
* @psalm-param AssociationMapping $assoc
*
* @return mixed
*/
@@ -314,7 +314,7 @@ interface EntityPersister
* @param object $sourceEntity
* @param int|null $offset
* @param int|null $limit
* @psalm-param array<string, mixed> $assoc
* @psalm-param AssociationMapping $assoc
*
* @return mixed[]
*/

View File

@@ -41,7 +41,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
private $quotedTableMap = [];
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getDiscriminatorColumnTableName()
{
@@ -104,7 +104,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function executeInserts()
{
@@ -199,7 +199,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function update($entity)
{
@@ -237,7 +237,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function delete($entity)
{
@@ -275,7 +275,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, ?array $orderBy = null)
{
@@ -369,7 +369,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getLockTablesSql($lockMode)
{
@@ -498,7 +498,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getInsertColumnList()
{
@@ -543,7 +543,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function assignDefaultVersionAndUpsertableValues($entity, array $id)
{

View File

@@ -10,6 +10,9 @@ use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Utility\PersisterHelper;
use function array_flip;
use function array_intersect;
use function array_map;
use function array_unshift;
use function implode;
/**
@@ -23,7 +26,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
use SQLResultCasing;
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getDiscriminatorColumnTableName()
{
@@ -31,7 +34,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getSelectColumnsSQL()
{
@@ -94,7 +97,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getInsertColumnList()
{
@@ -107,7 +110,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getSQLTableAlias($className, $assocName = '')
{
@@ -115,7 +118,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getSelectConditionSQL(array $criteria, $assoc = null)
{
@@ -129,7 +132,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function getSelectConditionCriteriaSQL(Criteria $criteria)
{
@@ -145,16 +148,13 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
/** @return string */
protected function getSelectConditionDiscriminatorValueSQL()
{
$values = [];
$values = array_map(
[$this->conn, 'quote'],
array_flip(array_intersect($this->class->discriminatorMap, $this->class->subClasses))
);
if ($this->class->discriminatorValue !== null) { // discriminators can be 0
$values[] = $this->conn->quote($this->class->discriminatorValue);
}
$discrValues = array_flip($this->class->discriminatorMap);
foreach ($this->class->subClasses as $subclassName) {
$values[] = $this->conn->quote($discrValues[$subclassName]);
array_unshift($values, $this->conn->quote($this->class->discriminatorValue));
}
$discColumnName = $this->class->getDiscriminatorColumn()['name'];
@@ -166,7 +166,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias)
{

View File

@@ -12,6 +12,7 @@ use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Persisters\Entity\BasicEntityPersister;
use RuntimeException;
use function defined;
use function implode;
use function in_array;
use function is_object;
@@ -81,6 +82,11 @@ class SqlExpressionVisitor extends ExpressionVisitor
return '(' . implode(' OR ', $expressionList) . ')';
default:
// Multiversion support for `doctrine/collections` before and after v2.1.0
if (defined(CompositeExpression::class . '::TYPE_NOT') && $expr->getType() === CompositeExpression::TYPE_NOT) {
return 'NOT (' . $expressionList[0] . ')';
}
throw new RuntimeException('Unknown composite ' . $expr->getType());
}
}

View File

@@ -27,18 +27,10 @@ class SqlValueVisitor extends ExpressionVisitor
*/
public function walkComparison(Comparison $comparison)
{
$value = $this->getValueFromComparison($comparison);
$field = $comparison->getField();
$operator = $comparison->getOperator();
if (($operator === Comparison::EQ || $operator === Comparison::IS) && $value === null) {
return null;
} elseif ($operator === Comparison::NEQ && $value === null) {
return null;
}
$value = $this->getValueFromComparison($comparison);
$this->values[] = $value;
$this->types[] = [$field, $value, $operator];
$this->types[] = [$comparison->getField(), $value, $comparison->getOperator()];
return null;
}

View File

@@ -122,7 +122,7 @@ final class Query extends AbstractQuery
* @var int
* @psalm-var self::STATE_*
*/
private $_state = self::STATE_DIRTY;
private $state = self::STATE_DIRTY;
/**
* A snapshot of the parameter types the query was parsed with.
@@ -210,7 +210,7 @@ final class Query extends AbstractQuery
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* @return ResultSetMapping
*/
@@ -239,11 +239,11 @@ final class Query extends AbstractQuery
}
// Return previous parser result if the query and the filter collection are both clean
if ($this->_state === self::STATE_CLEAN && $this->parsedTypes === $types && $this->_em->isFiltersStateClean()) {
if ($this->state === self::STATE_CLEAN && $this->parsedTypes === $types && $this->_em->isFiltersStateClean()) {
return $this->parserResult;
}
$this->_state = self::STATE_CLEAN;
$this->state = self::STATE_CLEAN;
$this->parsedTypes = $types;
$queryCache = $this->queryCache ?? $this->_em->getConfiguration()->getQueryCache();
@@ -279,7 +279,7 @@ final class Query extends AbstractQuery
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function _doExecute()
{
@@ -586,8 +586,8 @@ final class Query extends AbstractQuery
{
parent::free();
$this->dql = null;
$this->_state = self::STATE_CLEAN;
$this->dql = null;
$this->state = self::STATE_CLEAN;
}
/**
@@ -608,8 +608,8 @@ final class Query extends AbstractQuery
return $this;
}
$this->dql = $dqlQuery;
$this->_state = self::STATE_DIRTY;
$this->dql = $dqlQuery;
$this->state = self::STATE_DIRTY;
return $this;
}
@@ -635,7 +635,7 @@ final class Query extends AbstractQuery
*/
public function getState(): int
{
return $this->_state;
return $this->state;
}
/**
@@ -670,18 +670,18 @@ final class Query extends AbstractQuery
}
$this->firstResult = $firstResult;
$this->_state = self::STATE_DIRTY;
$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.
* Returns 0 if {@link setFirstResult} was not applied to this query.
*
* @return int|null The position of the first result.
* @return int The position of the first result.
*/
public function getFirstResult(): ?int
public function getFirstResult(): int
{
return $this->firstResult;
}
@@ -700,7 +700,7 @@ final class Query extends AbstractQuery
}
$this->maxResults = $maxResults;
$this->_state = self::STATE_DIRTY;
$this->state = self::STATE_DIRTY;
return $this;
}
@@ -743,21 +743,21 @@ final class Query extends AbstractQuery
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setHint($name, $value): self
{
$this->_state = self::STATE_DIRTY;
$this->state = self::STATE_DIRTY;
return parent::setHint($name, $value);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function setHydrationMode($hydrationMode): self
{
$this->_state = self::STATE_DIRTY;
$this->state = self::STATE_DIRTY;
return parent::setHydrationMode($hydrationMode);
}
@@ -831,6 +831,6 @@ final class Query extends AbstractQuery
{
parent::__clone();
$this->_state = self::STATE_DIRTY;
$this->state = self::STATE_DIRTY;
}
}

View File

@@ -32,7 +32,7 @@ class AggregateExpression extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($walker)
{

View File

@@ -30,7 +30,7 @@ class ArithmeticExpression extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($walker)
{

View File

@@ -44,7 +44,7 @@ class ArithmeticFactor extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -21,7 +21,7 @@ class ArithmeticTerm extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -32,7 +32,7 @@ class BetweenExpression extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -21,7 +21,7 @@ class CoalesceExpression extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -32,7 +32,7 @@ class CollectionMemberExpression extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($walker)
{

View File

@@ -38,7 +38,7 @@ class ComparisonExpression extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -21,7 +21,7 @@ class ConditionalExpression extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -25,7 +25,7 @@ class ConditionalFactor extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -30,7 +30,7 @@ class ConditionalPrimary extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -21,7 +21,7 @@ class ConditionalTerm extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -24,7 +24,7 @@ class DeleteClause extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -24,7 +24,7 @@ class DeleteStatement extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

View File

@@ -25,7 +25,7 @@ class EmptyCollectionComparisonExpression extends Node
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function dispatch($sqlWalker)
{

Some files were not shown because too many files have changed in this diff Show More