init
This commit is contained in:
19
backend/vendor/doctrine/orm/LICENSE
vendored
Normal file
19
backend/vendor/doctrine/orm/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) Doctrine Project
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
43
backend/vendor/doctrine/orm/README.md
vendored
Normal file
43
backend/vendor/doctrine/orm/README.md
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
| [4.0.x][4.0] | [3.7.x][3.7] | [3.6.x][3.6] | [2.21.x][2.21] | [2.20.x][2.20] |
|
||||
|:------------------------------------------------------:|:------------------------------------------------------:|:------------------------------------------------------:|:--------------------------------------------------------:|:--------------------------------------------------------:|
|
||||
| [![Build status][4.0 image]][4.0 workflow] | [![Build status][3.7 image]][3.7 workflow] | [![Build status][3.6 image]][3.6 workflow] | [![Build status][2.21 image]][2.21 workflow] | [![Build status][2.20 image]][2.20 workflow] |
|
||||
| [![Coverage Status][4.0 coverage image]][4.0 coverage] | [![Coverage Status][3.7 coverage image]][3.7 coverage] | [![Coverage Status][3.6 coverage image]][3.6 coverage] | [![Coverage Status][2.21 coverage image]][2.21 coverage] | [![Coverage Status][2.20 coverage image]][2.20 coverage] |
|
||||
|
||||
Doctrine ORM is an object-relational mapper for PHP 8.1+ that provides transparent persistence
|
||||
for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features
|
||||
is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL),
|
||||
inspired by Hibernate's HQL. This provides developers with a powerful alternative to SQL that maintains flexibility
|
||||
without requiring unnecessary code duplication.
|
||||
|
||||
|
||||
## More resources:
|
||||
|
||||
* [Website](http://www.doctrine-project.org)
|
||||
* [Documentation](https://www.doctrine-project.org/projects/doctrine-orm/en/stable/index.html)
|
||||
|
||||
|
||||
[4.0 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=4.0.x
|
||||
[4.0]: https://github.com/doctrine/orm/tree/4.0.x
|
||||
[4.0 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A4.0.x
|
||||
[4.0 coverage image]: https://codecov.io/gh/doctrine/orm/branch/4.0.x/graph/badge.svg
|
||||
[4.0 coverage]: https://codecov.io/gh/doctrine/orm/branch/4.0.x
|
||||
[3.7 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.7.x
|
||||
[3.7]: https://github.com/doctrine/orm/tree/3.7.x
|
||||
[3.7 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A3.7.x
|
||||
[3.7 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.7.x/graph/badge.svg
|
||||
[3.7 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.7.x
|
||||
[3.6 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.6.x
|
||||
[3.6]: https://github.com/doctrine/orm/tree/3.6.x
|
||||
[3.6 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A3.6.x
|
||||
[3.6 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.6.x/graph/badge.svg
|
||||
[3.6 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.6.x
|
||||
[2.21 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.21.x
|
||||
[2.21]: https://github.com/doctrine/orm/tree/2.21.x
|
||||
[2.21 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A2.21.x
|
||||
[2.21 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.21.x/graph/badge.svg
|
||||
[2.21 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.21.x
|
||||
[2.20 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.20.x
|
||||
[2.20]: https://github.com/doctrine/orm/tree/2.20.x
|
||||
[2.20 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A2.20.x
|
||||
[2.20 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.20.x/graph/badge.svg
|
||||
[2.20 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.20.x
|
||||
17
backend/vendor/doctrine/orm/SECURITY.md
vendored
Normal file
17
backend/vendor/doctrine/orm/SECURITY.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
Security
|
||||
========
|
||||
|
||||
The Doctrine library is operating very close to your database and as such needs
|
||||
to handle and make assumptions about SQL injection vulnerabilities.
|
||||
|
||||
It is vital that you understand how Doctrine approaches security, because
|
||||
we cannot protect you from SQL injection.
|
||||
|
||||
Please read the documentation chapter on Security in Doctrine DBAL and ORM to
|
||||
understand the assumptions we make.
|
||||
|
||||
- [DBAL Security Page](https://www.doctrine-project.org/projects/doctrine-dbal/en/stable/reference/security.html)
|
||||
- [ORM Security Page](https://www.doctrine-project.org/projects/doctrine-orm/en/stable/reference/security.html)
|
||||
|
||||
If you find a Security bug in Doctrine, please follow our
|
||||
[Security reporting guidelines](https://www.doctrine-project.org/policies/security.html#reporting).
|
||||
2667
backend/vendor/doctrine/orm/UPGRADE.md
vendored
Normal file
2667
backend/vendor/doctrine/orm/UPGRADE.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
86
backend/vendor/doctrine/orm/composer.json
vendored
Normal file
86
backend/vendor/doctrine/orm/composer.json
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"name": "doctrine/orm",
|
||||
"description": "Object-Relational-Mapper for PHP",
|
||||
"license": "MIT",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"orm",
|
||||
"database"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Marco Pivetta",
|
||||
"email": "ocramius@gmail.com"
|
||||
}
|
||||
],
|
||||
"homepage": "https://www.doctrine-project.org/projects/orm.html",
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"ext-ctype": "*",
|
||||
"composer-runtime-api": "^2",
|
||||
"doctrine/collections": "^2.2",
|
||||
"doctrine/dbal": "^3.8.2 || ^4",
|
||||
"doctrine/deprecations": "^0.5.3 || ^1",
|
||||
"doctrine/event-manager": "^1.2 || ^2",
|
||||
"doctrine/inflector": "^1.4 || ^2.0",
|
||||
"doctrine/instantiator": "^1.3 || ^2",
|
||||
"doctrine/lexer": "^3",
|
||||
"doctrine/persistence": "^3.3.1 || ^4",
|
||||
"psr/cache": "^1 || ^2 || ^3",
|
||||
"symfony/console": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/var-exporter": "^6.3.9 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^14.0",
|
||||
"phpbench/phpbench": "^1.0",
|
||||
"phpstan/extension-installer": "^1.4",
|
||||
"phpstan/phpstan": "2.1.23",
|
||||
"phpstan/phpstan-deprecation-rules": "^2",
|
||||
"phpunit/phpunit": "^10.5.0 || ^11.5",
|
||||
"psr/log": "^1 || ^2 || ^3",
|
||||
"symfony/cache": "^5.4 || ^6.2 || ^7.0 || ^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "Provides support for XSD validation for XML mapping files",
|
||||
"symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\ORM\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Performance\\": "tests/Performance",
|
||||
"Doctrine\\StaticAnalysis\\": "tests/StaticAnalysis",
|
||||
"Doctrine\\Tests\\": "tests/Tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true,
|
||||
"phpstan/extension-installer": true
|
||||
},
|
||||
"sort-packages": true
|
||||
},
|
||||
"scripts": {
|
||||
"docs": "composer --working-dir docs update && ./docs/vendor/bin/build-docs.sh @additional_args"
|
||||
}
|
||||
}
|
||||
600
backend/vendor/doctrine/orm/doctrine-mapping.xsd
vendored
Normal file
600
backend/vendor/doctrine/orm/doctrine-mapping.xsd
vendored
Normal file
@@ -0,0 +1,600 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:orm="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<xs:annotation>
|
||||
<xs:documentation><![CDATA[
|
||||
This is the XML Schema for the object/relational
|
||||
mapping file used by the Doctrine ORM.
|
||||
]]></xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
<xs:element name="doctrine-mapping">
|
||||
<xs:complexType>
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="mapped-superclass" type="orm:mapped-superclass" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="entity" type="orm:entity" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="embeddable" type="orm:embeddable" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:complexType name="emptyType">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="cascade-type">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="cascade-all" type="orm:emptyType" minOccurs="0"/>
|
||||
<xs:element name="cascade-persist" type="orm:emptyType" minOccurs="0"/>
|
||||
<xs:element name="cascade-remove" type="orm:emptyType" minOccurs="0"/>
|
||||
<xs:element name="cascade-refresh" type="orm:emptyType" minOccurs="0"/>
|
||||
<xs:element name="cascade-detach" type="orm:emptyType" minOccurs="0"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="lifecycle-callback-type">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="prePersist"/>
|
||||
<xs:enumeration value="postPersist"/>
|
||||
<xs:enumeration value="preUpdate"/>
|
||||
<xs:enumeration value="postUpdate"/>
|
||||
<xs:enumeration value="preRemove"/>
|
||||
<xs:enumeration value="postRemove"/>
|
||||
<xs:enumeration value="postLoad"/>
|
||||
<xs:enumeration value="preFlush"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="cache-usage-type">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="READ_ONLY"/>
|
||||
<xs:enumeration value="READ_WRITE"/>
|
||||
<xs:enumeration value="NONSTRICT_READ_WRITE"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="lifecycle-callback">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="type" type="orm:lifecycle-callback-type" use="required" />
|
||||
<xs:attribute name="method" type="xs:NMTOKEN" use="required" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="lifecycle-callbacks">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="lifecycle-callback" type="orm:lifecycle-callback" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="entity-listener">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="lifecycle-callback" type="orm:lifecycle-callback" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="class" type="orm:fqcn"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="entity-listeners">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="entity-listener" type="orm:entity-listener" minOccurs="1" maxOccurs="unbounded" />
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="column-result">
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="field-result">
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
<xs:attribute name="column" type="xs:string" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="entity-result">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="field-result" type="orm:field-result" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xs:choice>
|
||||
<xs:attribute name="entity-class" type="orm:fqcn" use="required" />
|
||||
<xs:attribute name="discriminator-column" type="xs:string" use="optional" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="cache">
|
||||
<xs:attribute name="usage" type="orm:cache-usage-type" />
|
||||
<xs:attribute name="region" type="xs:string" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="entity">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="cache" type="orm:cache" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="options" type="orm:options" minOccurs="0" />
|
||||
<xs:element name="indexes" type="orm:indexes" minOccurs="0"/>
|
||||
<xs:element name="unique-constraints" type="orm:unique-constraints" minOccurs="0"/>
|
||||
<xs:element name="discriminator-column" type="orm:discriminator-column" minOccurs="0"/>
|
||||
<xs:element name="discriminator-map" type="orm:discriminator-map" minOccurs="0"/>
|
||||
<xs:element name="lifecycle-callbacks" type="orm:lifecycle-callbacks" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="entity-listeners" type="orm:entity-listeners" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="id" type="orm:id" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="field" type="orm:field" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="embedded" type="orm:embedded" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="one-to-one" type="orm:one-to-one" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="one-to-many" type="orm:one-to-many" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="many-to-one" type="orm:many-to-one" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="many-to-many" type="orm:many-to-many" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="association-overrides" type="orm:association-overrides" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="attribute-overrides" type="orm:attribute-overrides" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
<xs:attribute name="table" type="orm:tablename" />
|
||||
<xs:attribute name="schema" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="repository-class" type="orm:fqcn"/>
|
||||
<xs:attribute name="inheritance-type" type="orm:inheritance-type"/>
|
||||
<xs:attribute name="change-tracking-policy" type="orm:change-tracking-policy" />
|
||||
<xs:attribute name="read-only" type="xs:boolean" default="false" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="tablename" id="tablename">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:pattern value="[a-zA-Z_u01-uff.]+" id="tablename.pattern">
|
||||
</xs:pattern>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="object">
|
||||
<xs:attribute name="class" type="xs:string" use="required"/>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="option" mixed="true">
|
||||
<xs:choice minOccurs="0" maxOccurs="1">
|
||||
<xs:element name="object" type="orm:object"/>
|
||||
<xs:sequence>
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="option" type="orm:option"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
</xs:sequence>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required"/>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="options">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="option" type="orm:option" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="mapped-superclass" >
|
||||
<xs:complexContent>
|
||||
<xs:extension base="orm:entity"/>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="embeddable">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="orm:entity"/>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="change-tracking-policy">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="DEFERRED_IMPLICIT"/>
|
||||
<xs:enumeration value="DEFERRED_EXPLICIT"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="inheritance-type">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="SINGLE_TABLE"/>
|
||||
<xs:enumeration value="JOINED"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="generator-strategy">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="NONE"/>
|
||||
<xs:enumeration value="SEQUENCE"/>
|
||||
<xs:enumeration value="IDENTITY"/>
|
||||
<xs:enumeration value="AUTO"/>
|
||||
<xs:enumeration value="CUSTOM" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="fk-action">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="CASCADE"/>
|
||||
<xs:enumeration value="RESTRICT"/>
|
||||
<xs:enumeration value="SET NULL"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="fetch-type">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="EAGER"/>
|
||||
<xs:enumeration value="LAZY"/>
|
||||
<xs:enumeration value="EXTRA_LAZY"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="generated-type">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="NEVER"/>
|
||||
<xs:enumeration value="INSERT"/>
|
||||
<xs:enumeration value="ALWAYS"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="field">
|
||||
<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" />
|
||||
<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" />
|
||||
<xs:attribute name="nullable" type="xs:boolean" default="false" />
|
||||
<xs:attribute name="index" type="xs:boolean" default="false" />
|
||||
<xs:attribute name="insertable" type="xs:boolean" default="true" />
|
||||
<xs:attribute name="updatable" type="xs:boolean" default="true" />
|
||||
<xs:attribute name="generated" type="orm:generated-type" default="NEVER" />
|
||||
<xs:attribute name="enum-type" type="xs:string" />
|
||||
<xs:attribute name="version" type="xs:boolean" />
|
||||
<xs:attribute name="column-definition" type="xs:string" />
|
||||
<xs:attribute name="precision" type="xs:integer" use="optional" />
|
||||
<xs:attribute name="scale" type="xs:integer" use="optional" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="embedded">
|
||||
<xs:sequence>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
<xs:attribute name="class" type="orm:fqcn" use="optional" />
|
||||
<xs:attribute name="column-prefix" type="xs:string" use="optional" />
|
||||
<xs:attribute name="use-column-prefix" type="xs:boolean" default="true" use="optional" />
|
||||
</xs:complexType>
|
||||
|
||||
<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" />
|
||||
<xs:attribute name="type" type="xs:NMTOKEN"/>
|
||||
<xs:attribute name="field-name" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="length" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="column-definition" type="xs:string" />
|
||||
<xs:attribute name="enum-type" type="xs:string" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="unique-constraint">
|
||||
<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="optional"/>
|
||||
<xs:attribute name="columns" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="fields" type="xs:string" use="optional"/>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="unique-constraints">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="unique-constraint" type="orm:unique-constraint" minOccurs="1" maxOccurs="unbounded"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="index">
|
||||
<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="optional"/>
|
||||
<xs:attribute name="columns" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="fields" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="flags" type="xs:string" use="optional"/>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="indexes">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="index" type="orm:index" minOccurs="1" maxOccurs="unbounded"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="discriminator-mapping">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="value" type="orm:type" use="required"/>
|
||||
<xs:attribute name="class" type="orm:fqcn" use="required"/>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="discriminator-map">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="discriminator-mapping" type="orm:discriminator-mapping" minOccurs="1" maxOccurs="unbounded"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="generator">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="strategy" type="orm:generator-strategy" use="optional" default="AUTO" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="id">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="generator" type="orm:generator" minOccurs="0" />
|
||||
<xs:element name="sequence-generator" type="orm:sequence-generator" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="custom-id-generator" type="orm:custom-id-generator" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="options" type="orm:options" minOccurs="0" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
<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" />
|
||||
<xs:attribute name="column-definition" type="xs:string" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="sequence-generator">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="sequence-name" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="allocation-size" type="xs:integer" use="optional" default="1" />
|
||||
<xs:attribute name="initial-value" type="xs:integer" use="optional" default="1" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="custom-id-generator">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="class" type="orm:fqcn" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="fqcn" id="fqcn">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:pattern value="[a-zA-Z_u01-uff][a-zA-Z0-9_u01-uff]+" id="fqcn.pattern">
|
||||
</xs:pattern>
|
||||
</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" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="join-column">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="optional" />
|
||||
<xs:attribute name="referenced-column-name" type="xs:NMTOKEN" use="optional" default="id" />
|
||||
<xs:attribute name="unique" type="xs:boolean" default="false" />
|
||||
<xs:attribute name="nullable" type="xs:boolean" default="true" />
|
||||
<xs:attribute name="on-delete" type="orm:fk-action" />
|
||||
<xs:attribute name="column-definition" type="xs:string" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="join-columns">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="join-column" type="orm:join-column" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="join-table">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="join-columns" type="orm:join-columns" />
|
||||
<xs:element name="inverse-join-columns" type="orm:join-columns" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="schema" type="xs:NMTOKEN" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="order-by">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="order-by-field" type="orm:order-by-field" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="order-by-field">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="direction" type="orm:order-by-direction" default="ASC" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="order-by-direction">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="ASC"/>
|
||||
<xs:enumeration value="DESC"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="columntoken" id="columntoken">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:pattern value="[-._:A-Za-z0-9`]+" id="columntoken.pattern"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="many-to-many">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="cache" type="orm:cache" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
|
||||
<xs:element name="join-table" type="orm:join-table" minOccurs="0" />
|
||||
<xs:element name="order-by" type="orm:order-by" minOccurs="0" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="target-entity" type="xs:string" use="required" />
|
||||
<xs:attribute name="mapped-by" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="inversed-by" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="index-by" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="fetch" type="orm:fetch-type" default="LAZY" />
|
||||
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="one-to-many">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="cache" type="orm:cache" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
|
||||
<xs:element name="order-by" type="orm:order-by" minOccurs="0" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="target-entity" type="xs:string" use="required" />
|
||||
<xs:attribute name="mapped-by" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="index-by" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="fetch" type="orm:fetch-type" default="LAZY" />
|
||||
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="many-to-one">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="cache" type="orm:cache" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
|
||||
<xs:choice minOccurs="0" maxOccurs="1">
|
||||
<xs:element name="join-column" type="orm:join-column"/>
|
||||
<xs:element name="join-columns" type="orm:join-columns"/>
|
||||
</xs:choice>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="target-entity" type="xs:string" />
|
||||
<xs:attribute name="inversed-by" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="fetch" type="orm:fetch-type" default="LAZY" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="one-to-one">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="cache" type="orm:cache" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
|
||||
<xs:choice minOccurs="0" maxOccurs="1">
|
||||
<xs:element name="join-column" type="orm:join-column"/>
|
||||
<xs:element name="join-columns" type="orm:join-columns"/>
|
||||
</xs:choice>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="target-entity" type="xs:string" />
|
||||
<xs:attribute name="mapped-by" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="inversed-by" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="fetch" type="orm:fetch-type" default="LAZY" />
|
||||
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="association-overrides">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="association-override" type="orm:association-override" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="association-override">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="join-table" type="orm:join-table" minOccurs="0" />
|
||||
<xs:element name="join-columns" type="orm:join-columns" minOccurs="0" />
|
||||
<xs:element name="inversed-by" type="orm:inversed-by-override" minOccurs="0" maxOccurs="1" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="fetch" type="orm:fetch-type" use="optional" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="inversed-by-override">
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="attribute-overrides">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="attribute-override" type="orm:attribute-override" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="attribute-override">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="field" type="orm:attribute-override-field" minOccurs="1" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="attribute-override-field">
|
||||
<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="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" />
|
||||
<xs:attribute name="nullable" type="xs:boolean" default="false" />
|
||||
<xs:attribute name="insertable" type="xs:boolean" default="true" />
|
||||
<xs:attribute name="updateable" type="xs:boolean" default="true" />
|
||||
<xs:attribute name="version" type="xs:boolean" />
|
||||
<xs:attribute name="column-definition" type="xs:string" />
|
||||
<xs:attribute name="precision" type="xs:integer" use="optional" />
|
||||
<xs:attribute name="scale" type="xs:integer" use="optional" />
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
</xs:schema>
|
||||
1111
backend/vendor/doctrine/orm/src/AbstractQuery.php
vendored
Normal file
1111
backend/vendor/doctrine/orm/src/AbstractQuery.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
106
backend/vendor/doctrine/orm/src/Cache.php
vendored
Normal file
106
backend/vendor/doctrine/orm/src/Cache.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\ORM\Cache\QueryCache;
|
||||
use Doctrine\ORM\Cache\Region;
|
||||
|
||||
/**
|
||||
* Provides an API for querying/managing the second level cache regions.
|
||||
*/
|
||||
interface Cache
|
||||
{
|
||||
public const DEFAULT_QUERY_REGION_NAME = 'query_cache_region';
|
||||
|
||||
public const DEFAULT_TIMESTAMP_REGION_NAME = 'timestamp_cache_region';
|
||||
|
||||
/**
|
||||
* May read items from the cache, but will not add items.
|
||||
*/
|
||||
public const MODE_GET = 1;
|
||||
|
||||
/**
|
||||
* Will never read items from the cache,
|
||||
* but will add items to the cache as it reads them from the database.
|
||||
*/
|
||||
public const MODE_PUT = 2;
|
||||
|
||||
/**
|
||||
* May read items from the cache, and add items to the cache.
|
||||
*/
|
||||
public const MODE_NORMAL = 3;
|
||||
|
||||
/**
|
||||
* The query will never read items from the cache,
|
||||
* but will refresh items to the cache as it reads them from the database.
|
||||
*/
|
||||
public const MODE_REFRESH = 4;
|
||||
|
||||
public function getEntityCacheRegion(string $className): Region|null;
|
||||
|
||||
public function getCollectionCacheRegion(string $className, string $association): Region|null;
|
||||
|
||||
/**
|
||||
* Determine whether the cache contains data for the given entity "instance".
|
||||
*/
|
||||
public function containsEntity(string $className, mixed $identifier): bool;
|
||||
|
||||
/**
|
||||
* Evicts the entity data for a particular entity "instance".
|
||||
*/
|
||||
public function evictEntity(string $className, mixed $identifier): void;
|
||||
|
||||
/**
|
||||
* Evicts all entity data from the given region.
|
||||
*/
|
||||
public function evictEntityRegion(string $className): void;
|
||||
|
||||
/**
|
||||
* Evict data from all entity regions.
|
||||
*/
|
||||
public function evictEntityRegions(): void;
|
||||
|
||||
/**
|
||||
* Determine whether the cache contains data for the given collection.
|
||||
*/
|
||||
public function containsCollection(string $className, string $association, mixed $ownerIdentifier): bool;
|
||||
|
||||
/**
|
||||
* Evicts the cache data for the given identified collection instance.
|
||||
*/
|
||||
public function evictCollection(string $className, string $association, mixed $ownerIdentifier): void;
|
||||
|
||||
/**
|
||||
* Evicts all entity data from the given region.
|
||||
*/
|
||||
public function evictCollectionRegion(string $className, string $association): void;
|
||||
|
||||
/**
|
||||
* Evict data from all collection regions.
|
||||
*/
|
||||
public function evictCollectionRegions(): void;
|
||||
|
||||
/**
|
||||
* Determine whether the cache contains data for the given query.
|
||||
*/
|
||||
public function containsQuery(string $regionName): bool;
|
||||
|
||||
/**
|
||||
* Evicts all cached query results under the given name, or default query cache if the region name is NULL.
|
||||
*/
|
||||
public function evictQueryRegion(string|null $regionName = null): void;
|
||||
|
||||
/**
|
||||
* Evict data from all query regions.
|
||||
*/
|
||||
public function evictQueryRegions(): void;
|
||||
|
||||
/**
|
||||
* Get query cache by region name or create a new one if none exist.
|
||||
*
|
||||
* @param string|null $regionName Query cache region name, or default query cache if the region name is NULL.
|
||||
*/
|
||||
public function getQueryCache(string|null $regionName = null): QueryCache;
|
||||
}
|
||||
30
backend/vendor/doctrine/orm/src/Cache/AssociationCacheEntry.php
vendored
Normal file
30
backend/vendor/doctrine/orm/src/Cache/AssociationCacheEntry.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
class AssociationCacheEntry implements CacheEntry
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $identifier The entity identifier.
|
||||
* @param class-string $class The entity class name
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $class,
|
||||
public readonly array $identifier,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AssociationCacheEntry
|
||||
*
|
||||
* This method allow Doctrine\Common\Cache\PhpFileCache compatibility
|
||||
*
|
||||
* @param array<string, mixed> $values array containing property values
|
||||
*/
|
||||
public static function __set_state(array $values): self
|
||||
{
|
||||
return new self($values['class'], $values['identifier']);
|
||||
}
|
||||
}
|
||||
60
backend/vendor/doctrine/orm/src/Cache/CacheConfiguration.php
vendored
Normal file
60
backend/vendor/doctrine/orm/src/Cache/CacheConfiguration.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Cache\Logging\CacheLogger;
|
||||
|
||||
/**
|
||||
* Configuration container for second-level cache.
|
||||
*/
|
||||
class CacheConfiguration
|
||||
{
|
||||
private CacheFactory|null $cacheFactory = null;
|
||||
private RegionsConfiguration|null $regionsConfig = null;
|
||||
private CacheLogger|null $cacheLogger = null;
|
||||
private QueryCacheValidator|null $queryValidator = null;
|
||||
|
||||
public function getCacheFactory(): CacheFactory|null
|
||||
{
|
||||
return $this->cacheFactory;
|
||||
}
|
||||
|
||||
public function setCacheFactory(CacheFactory $factory): void
|
||||
{
|
||||
$this->cacheFactory = $factory;
|
||||
}
|
||||
|
||||
public function getCacheLogger(): CacheLogger|null
|
||||
{
|
||||
return $this->cacheLogger;
|
||||
}
|
||||
|
||||
public function setCacheLogger(CacheLogger $logger): void
|
||||
{
|
||||
$this->cacheLogger = $logger;
|
||||
}
|
||||
|
||||
public function getRegionsConfiguration(): RegionsConfiguration
|
||||
{
|
||||
return $this->regionsConfig ??= new RegionsConfiguration();
|
||||
}
|
||||
|
||||
public function setRegionsConfiguration(RegionsConfiguration $regionsConfig): void
|
||||
{
|
||||
$this->regionsConfig = $regionsConfig;
|
||||
}
|
||||
|
||||
public function getQueryValidator(): QueryCacheValidator
|
||||
{
|
||||
return $this->queryValidator ??= new TimestampQueryCacheValidator(
|
||||
$this->cacheFactory->getTimestampRegion(),
|
||||
);
|
||||
}
|
||||
|
||||
public function setQueryValidator(QueryCacheValidator $validator): void
|
||||
{
|
||||
$this->queryValidator = $validator;
|
||||
}
|
||||
}
|
||||
16
backend/vendor/doctrine/orm/src/Cache/CacheEntry.php
vendored
Normal file
16
backend/vendor/doctrine/orm/src/Cache/CacheEntry.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
/**
|
||||
* Cache entry interface
|
||||
*
|
||||
* <b>IMPORTANT NOTE:</b>
|
||||
*
|
||||
* Fields of classes that implement CacheEntry are public for performance reason.
|
||||
*/
|
||||
interface CacheEntry
|
||||
{
|
||||
}
|
||||
26
backend/vendor/doctrine/orm/src/Cache/CacheException.php
vendored
Normal file
26
backend/vendor/doctrine/orm/src/Cache/CacheException.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Exception\ORMException;
|
||||
use LogicException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Exception for cache.
|
||||
*/
|
||||
class CacheException extends LogicException implements ORMException
|
||||
{
|
||||
public static function updateReadOnlyCollection(string $sourceEntity, string $fieldName): self
|
||||
{
|
||||
return new self(sprintf('Cannot update a readonly collection "%s#%s"', $sourceEntity, $fieldName));
|
||||
}
|
||||
|
||||
public static function nonCacheableEntity(string $entityName): self
|
||||
{
|
||||
return new self(sprintf('Entity "%s" not configured as part of the second-level cache.', $entityName));
|
||||
}
|
||||
}
|
||||
64
backend/vendor/doctrine/orm/src/Cache/CacheFactory.php
vendored
Normal file
64
backend/vendor/doctrine/orm/src/Cache/CacheFactory.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Cache;
|
||||
use Doctrine\ORM\Cache\Persister\Collection\CachedCollectionPersister;
|
||||
use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\AssociationMapping;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
|
||||
use Doctrine\ORM\Persisters\Entity\EntityPersister;
|
||||
|
||||
/**
|
||||
* Contract for building second level cache regions components.
|
||||
*/
|
||||
interface CacheFactory
|
||||
{
|
||||
/**
|
||||
* Build an entity persister for the given entity metadata.
|
||||
*/
|
||||
public function buildCachedEntityPersister(EntityManagerInterface $em, EntityPersister $persister, ClassMetadata $metadata): CachedEntityPersister;
|
||||
|
||||
/** Build a collection persister for the given relation mapping. */
|
||||
public function buildCachedCollectionPersister(
|
||||
EntityManagerInterface $em,
|
||||
CollectionPersister $persister,
|
||||
AssociationMapping $mapping,
|
||||
): CachedCollectionPersister;
|
||||
|
||||
/**
|
||||
* Build a query cache based on the given region name
|
||||
*/
|
||||
public function buildQueryCache(EntityManagerInterface $em, string|null $regionName = null): QueryCache;
|
||||
|
||||
/**
|
||||
* Build an entity hydrator
|
||||
*/
|
||||
public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata): EntityHydrator;
|
||||
|
||||
/**
|
||||
* Build a collection hydrator
|
||||
*/
|
||||
public function buildCollectionHydrator(EntityManagerInterface $em, AssociationMapping $mapping): CollectionHydrator;
|
||||
|
||||
/**
|
||||
* Build a cache region
|
||||
*
|
||||
* @param array<string,mixed> $cache The cache configuration.
|
||||
*/
|
||||
public function getRegion(array $cache): Region;
|
||||
|
||||
/**
|
||||
* Build timestamp cache region
|
||||
*/
|
||||
public function getTimestampRegion(): TimestampRegion;
|
||||
|
||||
/**
|
||||
* Build \Doctrine\ORM\Cache
|
||||
*/
|
||||
public function createCache(EntityManagerInterface $entityManager): Cache;
|
||||
}
|
||||
16
backend/vendor/doctrine/orm/src/Cache/CacheKey.php
vendored
Normal file
16
backend/vendor/doctrine/orm/src/Cache/CacheKey.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
/**
|
||||
* Defines entity / collection / query key to be stored in the cache region.
|
||||
* Allows multiple roles to be stored in the same cache region.
|
||||
*/
|
||||
abstract class CacheKey
|
||||
{
|
||||
public function __construct(public readonly string $hash)
|
||||
{
|
||||
}
|
||||
}
|
||||
25
backend/vendor/doctrine/orm/src/Cache/CollectionCacheEntry.php
vendored
Normal file
25
backend/vendor/doctrine/orm/src/Cache/CollectionCacheEntry.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
class CollectionCacheEntry implements CacheEntry
|
||||
{
|
||||
/** @param CacheKey[] $identifiers List of entity identifiers hold by the collection */
|
||||
public function __construct(public readonly array $identifiers)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CollectionCacheEntry
|
||||
*
|
||||
* This method allows for Doctrine\Common\Cache\PhpFileCache compatibility
|
||||
*
|
||||
* @param array<string, mixed> $values array containing property values
|
||||
*/
|
||||
public static function __set_state(array $values): CollectionCacheEntry
|
||||
{
|
||||
return new self($values['identifiers']);
|
||||
}
|
||||
}
|
||||
42
backend/vendor/doctrine/orm/src/Cache/CollectionCacheKey.php
vendored
Normal file
42
backend/vendor/doctrine/orm/src/Cache/CollectionCacheKey.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use function implode;
|
||||
use function ksort;
|
||||
use function str_replace;
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
* Defines entity collection roles to be stored in the cache region.
|
||||
*/
|
||||
class CollectionCacheKey extends CacheKey
|
||||
{
|
||||
/**
|
||||
* The owner entity identifier
|
||||
*
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
public readonly array $ownerIdentifier;
|
||||
|
||||
/**
|
||||
* @param class-string $entityClass The owner entity class.
|
||||
* @param array<string, mixed> $ownerIdentifier The identifier of the owning entity.
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $entityClass,
|
||||
public readonly string $association,
|
||||
array $ownerIdentifier,
|
||||
string $filterHash = '',
|
||||
) {
|
||||
ksort($ownerIdentifier);
|
||||
|
||||
$this->ownerIdentifier = $ownerIdentifier;
|
||||
|
||||
$filterHash = $filterHash === '' ? '' : '_' . $filterHash;
|
||||
|
||||
parent::__construct(str_replace('\\', '.', strtolower($entityClass)) . '_' . implode(' ', $ownerIdentifier) . '__' . $association . $filterHash);
|
||||
}
|
||||
}
|
||||
21
backend/vendor/doctrine/orm/src/Cache/CollectionHydrator.php
vendored
Normal file
21
backend/vendor/doctrine/orm/src/Cache/CollectionHydrator.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
|
||||
/**
|
||||
* Hydrator cache entry for collections
|
||||
*/
|
||||
interface CollectionHydrator
|
||||
{
|
||||
/** @param mixed[]|Collection $collection The collection. */
|
||||
public function buildCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, array|Collection $collection): CollectionCacheEntry;
|
||||
|
||||
/** @return mixed[]|null */
|
||||
public function loadCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, CollectionCacheEntry $entry, PersistentCollection $collection): array|null;
|
||||
}
|
||||
36
backend/vendor/doctrine/orm/src/Cache/ConcurrentRegion.php
vendored
Normal file
36
backend/vendor/doctrine/orm/src/Cache/ConcurrentRegion.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
/**
|
||||
* Defines contract for concurrently managed data region.
|
||||
* It should be able to lock an specific cache entry in an atomic operation.
|
||||
*
|
||||
* When a entry is locked another process should not be able to read or write the entry.
|
||||
* All evict operation should not consider locks, even though an entry is locked evict should be able to delete the entry and its lock.
|
||||
*/
|
||||
interface ConcurrentRegion extends Region
|
||||
{
|
||||
/**
|
||||
* Attempts to read lock the mapping for the given key.
|
||||
*
|
||||
* @param CacheKey $key The key of the item to lock.
|
||||
*
|
||||
* @return Lock|null A lock instance or NULL if the lock already exists.
|
||||
*
|
||||
* @throws LockException Indicates a problem accessing the region.
|
||||
*/
|
||||
public function lock(CacheKey $key): Lock|null;
|
||||
|
||||
/**
|
||||
* Attempts to read unlock the mapping for the given key.
|
||||
*
|
||||
* @param CacheKey $key The key of the item to unlock.
|
||||
* @param Lock $lock The lock previously obtained from {@link readLock}
|
||||
*
|
||||
* @throws LockException Indicates a problem accessing the region.
|
||||
*/
|
||||
public function unlock(CacheKey $key, Lock $lock): bool;
|
||||
}
|
||||
245
backend/vendor/doctrine/orm/src/Cache/DefaultCache.php
vendored
Normal file
245
backend/vendor/doctrine/orm/src/Cache/DefaultCache.php
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Cache;
|
||||
use Doctrine\ORM\Cache\Persister\CachedPersister;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\ORMInvalidArgumentException;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
|
||||
/**
|
||||
* Provides an API for querying/managing the second level cache regions.
|
||||
*/
|
||||
class DefaultCache implements Cache
|
||||
{
|
||||
private readonly UnitOfWork $uow;
|
||||
private readonly CacheFactory $cacheFactory;
|
||||
|
||||
/**
|
||||
* @var QueryCache[]
|
||||
* @phpstan-var array<string, QueryCache>
|
||||
*/
|
||||
private array $queryCaches = [];
|
||||
|
||||
private QueryCache|null $defaultQueryCache = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $em,
|
||||
) {
|
||||
$this->uow = $em->getUnitOfWork();
|
||||
$this->cacheFactory = $em->getConfiguration()
|
||||
->getSecondLevelCacheConfiguration()
|
||||
->getCacheFactory();
|
||||
}
|
||||
|
||||
public function getEntityCacheRegion(string $className): Region|null
|
||||
{
|
||||
$metadata = $this->em->getClassMetadata($className);
|
||||
$persister = $this->uow->getEntityPersister($metadata->rootEntityName);
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $persister->getCacheRegion();
|
||||
}
|
||||
|
||||
public function getCollectionCacheRegion(string $className, string $association): Region|null
|
||||
{
|
||||
$metadata = $this->em->getClassMetadata($className);
|
||||
$persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association));
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $persister->getCacheRegion();
|
||||
}
|
||||
|
||||
public function containsEntity(string $className, mixed $identifier): bool
|
||||
{
|
||||
$metadata = $this->em->getClassMetadata($className);
|
||||
$persister = $this->uow->getEntityPersister($metadata->rootEntityName);
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $persister->getCacheRegion()->contains($this->buildEntityCacheKey($metadata, $identifier));
|
||||
}
|
||||
|
||||
public function evictEntity(string $className, mixed $identifier): void
|
||||
{
|
||||
$metadata = $this->em->getClassMetadata($className);
|
||||
$persister = $this->uow->getEntityPersister($metadata->rootEntityName);
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$persister->getCacheRegion()->evict($this->buildEntityCacheKey($metadata, $identifier));
|
||||
}
|
||||
|
||||
public function evictEntityRegion(string $className): void
|
||||
{
|
||||
$metadata = $this->em->getClassMetadata($className);
|
||||
$persister = $this->uow->getEntityPersister($metadata->rootEntityName);
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$persister->getCacheRegion()->evictAll();
|
||||
}
|
||||
|
||||
public function evictEntityRegions(): void
|
||||
{
|
||||
$metadatas = $this->em->getMetadataFactory()->getAllMetadata();
|
||||
|
||||
foreach ($metadatas as $metadata) {
|
||||
$persister = $this->uow->getEntityPersister($metadata->rootEntityName);
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$persister->getCacheRegion()->evictAll();
|
||||
}
|
||||
}
|
||||
|
||||
public function containsCollection(string $className, string $association, mixed $ownerIdentifier): bool
|
||||
{
|
||||
$metadata = $this->em->getClassMetadata($className);
|
||||
$persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association));
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $persister->getCacheRegion()->contains($this->buildCollectionCacheKey($metadata, $association, $ownerIdentifier));
|
||||
}
|
||||
|
||||
public function evictCollection(string $className, string $association, mixed $ownerIdentifier): void
|
||||
{
|
||||
$metadata = $this->em->getClassMetadata($className);
|
||||
$persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association));
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$persister->getCacheRegion()->evict($this->buildCollectionCacheKey($metadata, $association, $ownerIdentifier));
|
||||
}
|
||||
|
||||
public function evictCollectionRegion(string $className, string $association): void
|
||||
{
|
||||
$metadata = $this->em->getClassMetadata($className);
|
||||
$persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association));
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$persister->getCacheRegion()->evictAll();
|
||||
}
|
||||
|
||||
public function evictCollectionRegions(): void
|
||||
{
|
||||
$metadatas = $this->em->getMetadataFactory()->getAllMetadata();
|
||||
|
||||
foreach ($metadatas as $metadata) {
|
||||
foreach ($metadata->associationMappings as $association) {
|
||||
if (! $association->isToMany()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$persister = $this->uow->getCollectionPersister($association);
|
||||
|
||||
if (! ($persister instanceof CachedPersister)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$persister->getCacheRegion()->evictAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function containsQuery(string $regionName): bool
|
||||
{
|
||||
return isset($this->queryCaches[$regionName]);
|
||||
}
|
||||
|
||||
public function evictQueryRegion(string|null $regionName = null): void
|
||||
{
|
||||
if ($regionName === null && $this->defaultQueryCache !== null) {
|
||||
$this->defaultQueryCache->clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->queryCaches[$regionName])) {
|
||||
$this->queryCaches[$regionName]->clear();
|
||||
}
|
||||
}
|
||||
|
||||
public function evictQueryRegions(): void
|
||||
{
|
||||
$this->getQueryCache()->clear();
|
||||
|
||||
foreach ($this->queryCaches as $queryCache) {
|
||||
$queryCache->clear();
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryCache(string|null $regionName = null): QueryCache
|
||||
{
|
||||
if ($regionName === null) {
|
||||
return $this->defaultQueryCache ??= $this->cacheFactory->buildQueryCache($this->em);
|
||||
}
|
||||
|
||||
return $this->queryCaches[$regionName] ??= $this->cacheFactory->buildQueryCache($this->em, $regionName);
|
||||
}
|
||||
|
||||
private function buildEntityCacheKey(ClassMetadata $metadata, mixed $identifier): EntityCacheKey
|
||||
{
|
||||
if (! is_array($identifier)) {
|
||||
$identifier = $this->toIdentifierArray($metadata, $identifier);
|
||||
}
|
||||
|
||||
return new EntityCacheKey($metadata->rootEntityName, $identifier);
|
||||
}
|
||||
|
||||
private function buildCollectionCacheKey(
|
||||
ClassMetadata $metadata,
|
||||
string $association,
|
||||
mixed $ownerIdentifier,
|
||||
): CollectionCacheKey {
|
||||
if (! is_array($ownerIdentifier)) {
|
||||
$ownerIdentifier = $this->toIdentifierArray($metadata, $ownerIdentifier);
|
||||
}
|
||||
|
||||
return new CollectionCacheKey($metadata->rootEntityName, $association, $ownerIdentifier);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function toIdentifierArray(ClassMetadata $metadata, mixed $identifier): array
|
||||
{
|
||||
if (is_object($identifier)) {
|
||||
$class = DefaultProxyClassNameResolver::getClass($identifier);
|
||||
if ($this->em->getMetadataFactory()->hasMetadataFor($class)) {
|
||||
$identifier = $this->uow->getSingleIdentifierValue($identifier)
|
||||
?? throw ORMInvalidArgumentException::invalidIdentifierBindingEntity($class);
|
||||
}
|
||||
}
|
||||
|
||||
return [$metadata->identifier[0] => $identifier];
|
||||
}
|
||||
}
|
||||
189
backend/vendor/doctrine/orm/src/Cache/DefaultCacheFactory.php
vendored
Normal file
189
backend/vendor/doctrine/orm/src/Cache/DefaultCacheFactory.php
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Cache;
|
||||
use Doctrine\ORM\Cache\Persister\Collection\CachedCollectionPersister;
|
||||
use Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister;
|
||||
use Doctrine\ORM\Cache\Persister\Collection\ReadOnlyCachedCollectionPersister;
|
||||
use Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister;
|
||||
use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister;
|
||||
use Doctrine\ORM\Cache\Persister\Entity\NonStrictReadWriteCachedEntityPersister;
|
||||
use Doctrine\ORM\Cache\Persister\Entity\ReadOnlyCachedEntityPersister;
|
||||
use Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister;
|
||||
use Doctrine\ORM\Cache\Region\DefaultRegion;
|
||||
use Doctrine\ORM\Cache\Region\FileLockRegion;
|
||||
use Doctrine\ORM\Cache\Region\UpdateTimestampCache;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\AssociationMapping;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
|
||||
use Doctrine\ORM\Persisters\Entity\EntityPersister;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
|
||||
use function assert;
|
||||
use function sprintf;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
class DefaultCacheFactory implements CacheFactory
|
||||
{
|
||||
private TimestampRegion|null $timestampRegion = null;
|
||||
|
||||
/** @var Region[] */
|
||||
private array $regions = [];
|
||||
|
||||
private string|null $fileLockRegionDirectory = null;
|
||||
|
||||
public function __construct(private readonly RegionsConfiguration $regionsConfig, private readonly CacheItemPoolInterface $cacheItemPool)
|
||||
{
|
||||
}
|
||||
|
||||
public function setFileLockRegionDirectory(string $fileLockRegionDirectory): void
|
||||
{
|
||||
$this->fileLockRegionDirectory = $fileLockRegionDirectory;
|
||||
}
|
||||
|
||||
public function getFileLockRegionDirectory(): string|null
|
||||
{
|
||||
return $this->fileLockRegionDirectory;
|
||||
}
|
||||
|
||||
public function setRegion(Region $region): void
|
||||
{
|
||||
$this->regions[$region->getName()] = $region;
|
||||
}
|
||||
|
||||
public function setTimestampRegion(TimestampRegion $region): void
|
||||
{
|
||||
$this->timestampRegion = $region;
|
||||
}
|
||||
|
||||
public function buildCachedEntityPersister(EntityManagerInterface $em, EntityPersister $persister, ClassMetadata $metadata): CachedEntityPersister
|
||||
{
|
||||
assert($metadata->cache !== null);
|
||||
$region = $this->getRegion($metadata->cache);
|
||||
$usage = $metadata->cache['usage'];
|
||||
|
||||
if ($usage === ClassMetadata::CACHE_USAGE_READ_ONLY) {
|
||||
return new ReadOnlyCachedEntityPersister($persister, $region, $em, $metadata);
|
||||
}
|
||||
|
||||
if ($usage === ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE) {
|
||||
return new NonStrictReadWriteCachedEntityPersister($persister, $region, $em, $metadata);
|
||||
}
|
||||
|
||||
if ($usage === ClassMetadata::CACHE_USAGE_READ_WRITE) {
|
||||
if (! $region instanceof ConcurrentRegion) {
|
||||
throw new InvalidArgumentException(sprintf('Unable to use access strategy type of [%s] without a ConcurrentRegion', $usage));
|
||||
}
|
||||
|
||||
return new ReadWriteCachedEntityPersister($persister, $region, $em, $metadata);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('Unrecognized access strategy type [%s]', $usage));
|
||||
}
|
||||
|
||||
public function buildCachedCollectionPersister(
|
||||
EntityManagerInterface $em,
|
||||
CollectionPersister $persister,
|
||||
AssociationMapping $mapping,
|
||||
): CachedCollectionPersister {
|
||||
assert(isset($mapping->cache));
|
||||
$usage = $mapping->cache['usage'];
|
||||
$region = $this->getRegion($mapping->cache);
|
||||
|
||||
if ($usage === ClassMetadata::CACHE_USAGE_READ_ONLY) {
|
||||
return new ReadOnlyCachedCollectionPersister($persister, $region, $em, $mapping);
|
||||
}
|
||||
|
||||
if ($usage === ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE) {
|
||||
return new NonStrictReadWriteCachedCollectionPersister($persister, $region, $em, $mapping);
|
||||
}
|
||||
|
||||
if ($usage === ClassMetadata::CACHE_USAGE_READ_WRITE) {
|
||||
if (! $region instanceof ConcurrentRegion) {
|
||||
throw new InvalidArgumentException(sprintf('Unable to use access strategy type of [%s] without a ConcurrentRegion', $usage));
|
||||
}
|
||||
|
||||
return new ReadWriteCachedCollectionPersister($persister, $region, $em, $mapping);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('Unrecognized access strategy type [%s]', $usage));
|
||||
}
|
||||
|
||||
public function buildQueryCache(EntityManagerInterface $em, string|null $regionName = null): QueryCache
|
||||
{
|
||||
return new DefaultQueryCache(
|
||||
$em,
|
||||
$this->getRegion(
|
||||
[
|
||||
'region' => $regionName ?: Cache::DEFAULT_QUERY_REGION_NAME,
|
||||
'usage' => ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function buildCollectionHydrator(EntityManagerInterface $em, AssociationMapping $mapping): CollectionHydrator
|
||||
{
|
||||
return new DefaultCollectionHydrator($em);
|
||||
}
|
||||
|
||||
public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata): EntityHydrator
|
||||
{
|
||||
return new DefaultEntityHydrator($em);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getRegion(array $cache): Region
|
||||
{
|
||||
if (isset($this->regions[$cache['region']])) {
|
||||
return $this->regions[$cache['region']];
|
||||
}
|
||||
|
||||
$name = $cache['region'];
|
||||
$lifetime = $this->regionsConfig->getLifetime($cache['region']);
|
||||
$region = new DefaultRegion($name, $this->cacheItemPool, $lifetime);
|
||||
|
||||
if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) {
|
||||
if (
|
||||
$this->fileLockRegionDirectory === '' ||
|
||||
$this->fileLockRegionDirectory === null
|
||||
) {
|
||||
throw new LogicException(
|
||||
'If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, ' .
|
||||
'The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you want to use it please provide a valid directory, DefaultCacheFactory#setFileLockRegionDirectory(). ',
|
||||
);
|
||||
}
|
||||
|
||||
$directory = $this->fileLockRegionDirectory . DIRECTORY_SEPARATOR . $cache['region'];
|
||||
$region = new FileLockRegion($region, $directory, (string) $this->regionsConfig->getLockLifetime($cache['region']));
|
||||
}
|
||||
|
||||
return $this->regions[$cache['region']] = $region;
|
||||
}
|
||||
|
||||
public function getTimestampRegion(): TimestampRegion
|
||||
{
|
||||
if ($this->timestampRegion === null) {
|
||||
$name = Cache::DEFAULT_TIMESTAMP_REGION_NAME;
|
||||
$lifetime = $this->regionsConfig->getLifetime($name);
|
||||
|
||||
$this->timestampRegion = new UpdateTimestampCache($name, $this->cacheItemPool, $lifetime);
|
||||
}
|
||||
|
||||
return $this->timestampRegion;
|
||||
}
|
||||
|
||||
public function createCache(EntityManagerInterface $entityManager): Cache
|
||||
{
|
||||
return new DefaultCache($entityManager);
|
||||
}
|
||||
}
|
||||
75
backend/vendor/doctrine/orm/src/Cache/DefaultCollectionHydrator.php
vendored
Normal file
75
backend/vendor/doctrine/orm/src/Cache/DefaultCollectionHydrator.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Cache\Persister\CachedPersister;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
use function assert;
|
||||
|
||||
/**
|
||||
* Default hydrator cache for collections
|
||||
*/
|
||||
class DefaultCollectionHydrator implements CollectionHydrator
|
||||
{
|
||||
private readonly UnitOfWork $uow;
|
||||
|
||||
/** @var array<string,mixed> */
|
||||
private static array $hints = [Query::HINT_CACHE_ENABLED => true];
|
||||
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $em,
|
||||
) {
|
||||
$this->uow = $em->getUnitOfWork();
|
||||
}
|
||||
|
||||
public function buildCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, array|Collection $collection): CollectionCacheEntry
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($collection as $index => $entity) {
|
||||
$data[$index] = new EntityCacheKey($metadata->rootEntityName, $this->uow->getEntityIdentifier($entity));
|
||||
}
|
||||
|
||||
return new CollectionCacheEntry($data);
|
||||
}
|
||||
|
||||
public function loadCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, CollectionCacheEntry $entry, PersistentCollection $collection): array|null
|
||||
{
|
||||
$assoc = $metadata->associationMappings[$key->association];
|
||||
$targetPersister = $this->uow->getEntityPersister($assoc->targetEntity);
|
||||
assert($targetPersister instanceof CachedPersister);
|
||||
$targetRegion = $targetPersister->getCacheRegion();
|
||||
$list = [];
|
||||
|
||||
/** @var EntityCacheEntry[]|null $entityEntries */
|
||||
$entityEntries = $targetRegion->getMultiple($entry);
|
||||
|
||||
if ($entityEntries === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($entityEntries as $index => $entityEntry) {
|
||||
$entity = $this->uow->createEntity(
|
||||
$entityEntry->class,
|
||||
$entityEntry->resolveAssociationEntries($this->em),
|
||||
self::$hints,
|
||||
);
|
||||
|
||||
$collection->hydrateSet($index, $entity);
|
||||
|
||||
$list[$index] = $entity;
|
||||
}
|
||||
|
||||
$this->uow->hydrationComplete();
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
176
backend/vendor/doctrine/orm/src/Cache/DefaultEntityHydrator.php
vendored
Normal file
176
backend/vendor/doctrine/orm/src/Cache/DefaultEntityHydrator.php
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
use Doctrine\ORM\Utility\IdentifierFlattener;
|
||||
|
||||
use function assert;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function reset;
|
||||
|
||||
/**
|
||||
* Default hydrator cache for entities
|
||||
*/
|
||||
class DefaultEntityHydrator implements EntityHydrator
|
||||
{
|
||||
private readonly UnitOfWork $uow;
|
||||
private readonly IdentifierFlattener $identifierFlattener;
|
||||
|
||||
/** @var array<string,mixed> */
|
||||
private static array $hints = [Query::HINT_CACHE_ENABLED => true];
|
||||
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $em,
|
||||
) {
|
||||
$this->uow = $em->getUnitOfWork();
|
||||
$this->identifierFlattener = new IdentifierFlattener($em->getUnitOfWork(), $em->getMetadataFactory());
|
||||
}
|
||||
|
||||
public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, object $entity): EntityCacheEntry
|
||||
{
|
||||
$data = $this->uow->getOriginalEntityData($entity);
|
||||
$data = [...$data, ...$metadata->getIdentifierValues($entity)]; // why update has no identifier values ?
|
||||
|
||||
if ($metadata->requiresFetchAfterChange) {
|
||||
if ($metadata->isVersioned) {
|
||||
assert($metadata->versionField !== null);
|
||||
$data[$metadata->versionField] = $metadata->getFieldValue($entity, $metadata->versionField);
|
||||
}
|
||||
|
||||
foreach ($metadata->fieldMappings as $name => $fieldMapping) {
|
||||
if (isset($fieldMapping->generated)) {
|
||||
$data[$name] = $metadata->getFieldValue($entity, $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($metadata->associationMappings as $name => $assoc) {
|
||||
if (! isset($data[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $assoc->isToOne()) {
|
||||
unset($data[$name]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! isset($assoc->cache)) {
|
||||
$targetClassMetadata = $this->em->getClassMetadata($assoc->targetEntity);
|
||||
$owningAssociation = $this->em->getMetadataFactory()->getOwningSide($assoc);
|
||||
$associationIds = $this->identifierFlattener->flattenIdentifier(
|
||||
$targetClassMetadata,
|
||||
$targetClassMetadata->getIdentifierValues($data[$name]),
|
||||
);
|
||||
|
||||
unset($data[$name]);
|
||||
|
||||
foreach ($associationIds as $fieldName => $fieldValue) {
|
||||
if (isset($targetClassMetadata->fieldMappings[$fieldName])) {
|
||||
assert($owningAssociation->isToOneOwningSide());
|
||||
$fieldMapping = $targetClassMetadata->fieldMappings[$fieldName];
|
||||
|
||||
$data[$owningAssociation->targetToSourceKeyColumns[$fieldMapping->columnName]] = $fieldValue;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$targetAssoc = $targetClassMetadata->associationMappings[$fieldName];
|
||||
|
||||
assert($assoc->isToOneOwningSide());
|
||||
foreach ($assoc->targetToSourceKeyColumns as $referencedColumn => $localColumn) {
|
||||
if (isset($targetAssoc->sourceToTargetKeyColumns[$referencedColumn])) {
|
||||
$data[$localColumn] = $fieldValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! isset($assoc->id)) {
|
||||
$targetClass = DefaultProxyClassNameResolver::getClass($data[$name]);
|
||||
$targetId = $this->uow->getEntityIdentifier($data[$name]);
|
||||
$data[$name] = new AssociationCacheEntry($targetClass, $targetId);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle association identifier
|
||||
$targetId = is_object($data[$name]) && $this->uow->isInIdentityMap($data[$name])
|
||||
? $this->uow->getEntityIdentifier($data[$name])
|
||||
: $data[$name];
|
||||
|
||||
// @TODO - fix it !
|
||||
// handle UnitOfWork#createEntity hash generation
|
||||
if (! is_array($targetId)) {
|
||||
assert($assoc->isToOneOwningSide());
|
||||
$data[reset($assoc->joinColumnFieldNames)] = $targetId;
|
||||
|
||||
$targetEntity = $this->em->getClassMetadata($assoc->targetEntity);
|
||||
$targetId = [$targetEntity->identifier[0] => $targetId];
|
||||
}
|
||||
|
||||
$data[$name] = new AssociationCacheEntry($assoc->targetEntity, $targetId);
|
||||
}
|
||||
|
||||
return new EntityCacheEntry($metadata->name, $data);
|
||||
}
|
||||
|
||||
public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, object|null $entity = null): object|null
|
||||
{
|
||||
$data = $entry->data;
|
||||
$hints = self::$hints;
|
||||
|
||||
if ($entity !== null) {
|
||||
$hints[Query::HINT_REFRESH] = true;
|
||||
$hints[Query::HINT_REFRESH_ENTITY] = $entity;
|
||||
}
|
||||
|
||||
foreach ($metadata->associationMappings as $name => $assoc) {
|
||||
if (! isset($assoc->cache) || ! isset($data[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$assocClass = $data[$name]->class;
|
||||
$assocId = $data[$name]->identifier;
|
||||
$isEagerLoad = ($assoc->fetch === ClassMetadata::FETCH_EAGER || ($assoc->isOneToOne() && ! $assoc->isOwningSide()));
|
||||
|
||||
if (! $isEagerLoad) {
|
||||
$data[$name] = $this->em->getReference($assocClass, $assocId);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$assocMetadata = $this->em->getClassMetadata($assoc->targetEntity);
|
||||
$assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocId);
|
||||
$assocPersister = $this->uow->getEntityPersister($assoc->targetEntity);
|
||||
$assocRegion = $assocPersister->getCacheRegion();
|
||||
$assocEntry = $assocRegion->get($assocKey);
|
||||
|
||||
if ($assocEntry === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data[$name] = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), $hints);
|
||||
}
|
||||
|
||||
if ($entity !== null) {
|
||||
$this->uow->registerManaged($entity, $key->identifier, $data);
|
||||
}
|
||||
|
||||
$result = $this->uow->createEntity($entry->class, $data, $hints);
|
||||
|
||||
$this->uow->hydrationComplete();
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
418
backend/vendor/doctrine/orm/src/Cache/DefaultQueryCache.php
vendored
Normal file
418
backend/vendor/doctrine/orm/src/Cache/DefaultQueryCache.php
vendored
Normal file
@@ -0,0 +1,418 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Cache;
|
||||
use Doctrine\ORM\Cache\Exception\FeatureNotImplemented;
|
||||
use Doctrine\ORM\Cache\Exception\NonCacheableEntity;
|
||||
use Doctrine\ORM\Cache\Logging\CacheLogger;
|
||||
use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\AssociationMapping;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
use function array_map;
|
||||
use function array_shift;
|
||||
use function array_unshift;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function is_array;
|
||||
use function key;
|
||||
use function reset;
|
||||
|
||||
/**
|
||||
* Default query cache implementation.
|
||||
*/
|
||||
class DefaultQueryCache implements QueryCache
|
||||
{
|
||||
private readonly UnitOfWork $uow;
|
||||
private readonly QueryCacheValidator $validator;
|
||||
protected CacheLogger|null $cacheLogger = null;
|
||||
|
||||
/** @var array<string,mixed> */
|
||||
private static array $hints = [Query::HINT_CACHE_ENABLED => true];
|
||||
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly Region $region,
|
||||
) {
|
||||
$cacheConfig = $em->getConfiguration()->getSecondLevelCacheConfiguration();
|
||||
|
||||
$this->uow = $em->getUnitOfWork();
|
||||
$this->cacheLogger = $cacheConfig->getCacheLogger();
|
||||
$this->validator = $cacheConfig->getQueryValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get(QueryCacheKey $key, ResultSetMapping $rsm, array $hints = []): array|null
|
||||
{
|
||||
if (! ($key->cacheMode & Cache::MODE_GET)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cacheEntry = $this->region->get($key);
|
||||
|
||||
if (! $cacheEntry instanceof QueryCacheEntry) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->validator->isValid($key, $cacheEntry)) {
|
||||
$this->region->evict($key);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$entityName = reset($rsm->aliasMap);
|
||||
$hasRelation = ! empty($rsm->relationMap);
|
||||
$persister = $this->uow->getEntityPersister($entityName);
|
||||
assert($persister instanceof CachedEntityPersister);
|
||||
|
||||
$region = $persister->getCacheRegion();
|
||||
$regionName = $region->getName();
|
||||
|
||||
$cm = $this->em->getClassMetadata($entityName);
|
||||
|
||||
$generateKeys = static fn (array $entry): EntityCacheKey => new EntityCacheKey($cm->rootEntityName, $entry['identifier']);
|
||||
|
||||
$cacheKeys = new CollectionCacheEntry(array_map($generateKeys, $cacheEntry->result));
|
||||
$entries = $region->getMultiple($cacheKeys) ?? [];
|
||||
|
||||
// @TODO - move to cache hydration component
|
||||
foreach ($cacheEntry->result as $index => $entry) {
|
||||
$entityEntry = $entries[$index] ?? null;
|
||||
|
||||
if (! $entityEntry instanceof EntityCacheEntry) {
|
||||
$this->cacheLogger?->entityCacheMiss($regionName, $cacheKeys->identifiers[$index]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->cacheLogger?->entityCacheHit($regionName, $cacheKeys->identifiers[$index]);
|
||||
|
||||
if (! $hasRelation) {
|
||||
$result[$index] = $this->uow->createEntity($entityEntry->class, $entityEntry->resolveAssociationEntries($this->em), self::$hints);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = $entityEntry->data;
|
||||
|
||||
foreach ($entry['associations'] as $name => $assoc) {
|
||||
$assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']);
|
||||
assert($assocPersister instanceof CachedEntityPersister);
|
||||
|
||||
$assocRegion = $assocPersister->getCacheRegion();
|
||||
$assocMetadata = $this->em->getClassMetadata($assoc['targetEntity']);
|
||||
|
||||
if ($assoc['type'] & ClassMetadata::TO_ONE) {
|
||||
$assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assoc['identifier']);
|
||||
$assocEntry = $assocRegion->get($assocKey);
|
||||
|
||||
if ($assocEntry === null) {
|
||||
$this->cacheLogger?->entityCacheMiss($assocRegion->getName(), $assocKey);
|
||||
|
||||
$this->uow->hydrationComplete();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$data[$name] = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), self::$hints);
|
||||
|
||||
$this->cacheLogger?->entityCacheHit($assocRegion->getName(), $assocKey);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! isset($assoc['list']) || empty($assoc['list'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$generateKeys = static fn (array $id): EntityCacheKey => new EntityCacheKey($assocMetadata->rootEntityName, $id);
|
||||
|
||||
$collection = new PersistentCollection($this->em, $assocMetadata, new ArrayCollection());
|
||||
$assocKeys = new CollectionCacheEntry(array_map($generateKeys, $assoc['list']));
|
||||
$assocEntries = $assocRegion->getMultiple($assocKeys);
|
||||
|
||||
foreach ($assoc['list'] as $assocIndex => $assocId) {
|
||||
$assocEntry = is_array($assocEntries) ? ($assocEntries[$assocIndex] ?? null) : null;
|
||||
|
||||
if ($assocEntry === null) {
|
||||
$this->cacheLogger?->entityCacheMiss($assocRegion->getName(), $assocKeys->identifiers[$assocIndex]);
|
||||
|
||||
$this->uow->hydrationComplete();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$element = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), self::$hints);
|
||||
|
||||
$collection->hydrateSet($assocIndex, $element);
|
||||
|
||||
$this->cacheLogger?->entityCacheHit($assocRegion->getName(), $assocKeys->identifiers[$assocIndex]);
|
||||
}
|
||||
|
||||
$data[$name] = $collection;
|
||||
|
||||
$collection->setInitialized(true);
|
||||
}
|
||||
|
||||
foreach ($data as $fieldName => $unCachedAssociationData) {
|
||||
// In some scenarios, such as EAGER+ASSOCIATION+ID+CACHE, the
|
||||
// cache key information in `$cacheEntry` will not contain details
|
||||
// for fields that are associations.
|
||||
//
|
||||
// This means that `$data` keys for some associations that may
|
||||
// actually not be cached will not be converted to actual association
|
||||
// data, yet they contain L2 cache AssociationCacheEntry objects.
|
||||
//
|
||||
// We need to unwrap those associations into proxy references,
|
||||
// since we don't have actual data for them except for identifiers.
|
||||
if ($unCachedAssociationData instanceof AssociationCacheEntry) {
|
||||
$data[$fieldName] = $this->em->getReference(
|
||||
$unCachedAssociationData->class,
|
||||
$unCachedAssociationData->identifier,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$result[$index] = $this->uow->createEntity($entityEntry->class, $data, self::$hints);
|
||||
}
|
||||
|
||||
$this->uow->hydrationComplete();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function put(QueryCacheKey $key, ResultSetMapping $rsm, mixed $result, array $hints = []): bool
|
||||
{
|
||||
if ($rsm->scalarMappings) {
|
||||
throw FeatureNotImplemented::scalarResults();
|
||||
}
|
||||
|
||||
if (count($rsm->entityMappings) > 1) {
|
||||
throw FeatureNotImplemented::multipleRootEntities();
|
||||
}
|
||||
|
||||
if (! $rsm->isSelect) {
|
||||
throw FeatureNotImplemented::nonSelectStatements();
|
||||
}
|
||||
|
||||
if (($hints[SqlWalker::HINT_PARTIAL] ?? false) === true || ($hints[Query::HINT_FORCE_PARTIAL_LOAD] ?? false) === true) {
|
||||
throw FeatureNotImplemented::partialEntities();
|
||||
}
|
||||
|
||||
if (! ($key->cacheMode & Cache::MODE_PUT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = [];
|
||||
$entityName = reset($rsm->aliasMap);
|
||||
$rootAlias = key($rsm->aliasMap);
|
||||
$persister = $this->uow->getEntityPersister($entityName);
|
||||
|
||||
if (! $persister instanceof CachedEntityPersister) {
|
||||
throw NonCacheableEntity::fromEntity($entityName);
|
||||
}
|
||||
|
||||
$region = $persister->getCacheRegion();
|
||||
|
||||
$cm = $this->em->getClassMetadata($entityName);
|
||||
|
||||
foreach ($result as $index => $entity) {
|
||||
$identifier = $this->uow->getEntityIdentifier($entity);
|
||||
$entityKey = new EntityCacheKey($cm->rootEntityName, $identifier);
|
||||
|
||||
if (($key->cacheMode & Cache::MODE_REFRESH) || ! $region->contains($entityKey)) {
|
||||
// Cancel put result if entity put fail
|
||||
if (! $persister->storeEntityCache($entity, $entityKey)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$data[$index]['identifier'] = $identifier;
|
||||
$data[$index]['associations'] = [];
|
||||
|
||||
// @TODO - move to cache hydration components
|
||||
foreach ($rsm->relationMap as $alias => $name) {
|
||||
$parentAlias = $rsm->parentAliasMap[$alias];
|
||||
$parentClass = $rsm->aliasMap[$parentAlias];
|
||||
$metadata = $this->em->getClassMetadata($parentClass);
|
||||
$assoc = $metadata->associationMappings[$name];
|
||||
$assocValue = $this->getAssociationValue($rsm, $alias, $entity);
|
||||
|
||||
if ($assocValue === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// root entity association
|
||||
if ($rootAlias === $parentAlias) {
|
||||
// Cancel put result if association put fail
|
||||
$assocInfo = $this->storeAssociationCache($key, $assoc, $assocValue);
|
||||
if ($assocInfo === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data[$index]['associations'][$name] = $assocInfo;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// store single nested association
|
||||
if (! is_array($assocValue)) {
|
||||
// Cancel put result if association put fail
|
||||
if ($this->storeAssociationCache($key, $assoc, $assocValue) === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// store array of nested association
|
||||
foreach ($assocValue as $aVal) {
|
||||
// Cancel put result if association put fail
|
||||
if ($this->storeAssociationCache($key, $assoc, $aVal) === null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->region->put($key, new QueryCacheEntry($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]|null
|
||||
* @phpstan-return array{targetEntity: class-string, type: mixed, list?: array[], identifier?: array}|null
|
||||
*/
|
||||
private function storeAssociationCache(QueryCacheKey $key, AssociationMapping $assoc, mixed $assocValue): array|null
|
||||
{
|
||||
$assocPersister = $this->uow->getEntityPersister($assoc->targetEntity);
|
||||
$assocMetadata = $assocPersister->getClassMetadata();
|
||||
$assocRegion = $assocPersister->getCacheRegion();
|
||||
|
||||
// Handle *-to-one associations
|
||||
if ($assoc->isToOne()) {
|
||||
$assocIdentifier = $this->uow->getEntityIdentifier($assocValue);
|
||||
$entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier);
|
||||
|
||||
if (! $this->uow->isUninitializedObject($assocValue) && ($key->cacheMode & Cache::MODE_REFRESH) || ! $assocRegion->contains($entityKey)) {
|
||||
// Entity put fail
|
||||
if (! $assocPersister->storeEntityCache($assocValue, $entityKey)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'targetEntity' => $assocMetadata->rootEntityName,
|
||||
'identifier' => $assocIdentifier,
|
||||
'type' => $assoc->type(),
|
||||
];
|
||||
}
|
||||
|
||||
// Handle *-to-many associations
|
||||
$list = [];
|
||||
|
||||
foreach ($assocValue as $assocItemIndex => $assocItem) {
|
||||
$assocIdentifier = $this->uow->getEntityIdentifier($assocItem);
|
||||
$entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier);
|
||||
|
||||
if (($key->cacheMode & Cache::MODE_REFRESH) || ! $assocRegion->contains($entityKey)) {
|
||||
// Entity put fail
|
||||
if (! $assocPersister->storeEntityCache($assocItem, $entityKey)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$list[$assocItemIndex] = $assocIdentifier;
|
||||
}
|
||||
|
||||
return [
|
||||
'targetEntity' => $assocMetadata->rootEntityName,
|
||||
'type' => $assoc->type(),
|
||||
'list' => $list,
|
||||
];
|
||||
}
|
||||
|
||||
/** @phpstan-return list<mixed>|object|null */
|
||||
private function getAssociationValue(
|
||||
ResultSetMapping $rsm,
|
||||
string $assocAlias,
|
||||
object $entity,
|
||||
): array|object|null {
|
||||
$path = [];
|
||||
$alias = $assocAlias;
|
||||
|
||||
while (isset($rsm->parentAliasMap[$alias])) {
|
||||
$parent = $rsm->parentAliasMap[$alias];
|
||||
$field = $rsm->relationMap[$alias];
|
||||
$class = $rsm->aliasMap[$parent];
|
||||
|
||||
array_unshift($path, [
|
||||
'field' => $field,
|
||||
'class' => $class,
|
||||
]);
|
||||
|
||||
$alias = $parent;
|
||||
}
|
||||
|
||||
return $this->getAssociationPathValue($entity, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param array<array-key, array{field: string, class: string}> $path
|
||||
*
|
||||
* @phpstan-return list<mixed>|object|null
|
||||
*/
|
||||
private function getAssociationPathValue(mixed $value, array $path): array|object|null
|
||||
{
|
||||
$mapping = array_shift($path);
|
||||
$metadata = $this->em->getClassMetadata($mapping['class']);
|
||||
$assoc = $metadata->associationMappings[$mapping['field']];
|
||||
$value = $metadata->getFieldValue($value, $mapping['field']);
|
||||
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($path === []) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Handle *-to-one associations
|
||||
if ($assoc->isToOne()) {
|
||||
return $this->getAssociationPathValue($value, $path);
|
||||
}
|
||||
|
||||
$values = [];
|
||||
|
||||
foreach ($value as $item) {
|
||||
$values[] = $this->getAssociationPathValue($item, $path);
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
public function clear(): bool
|
||||
{
|
||||
return $this->region->evictAll();
|
||||
}
|
||||
|
||||
public function getRegion(): Region
|
||||
{
|
||||
return $this->region;
|
||||
}
|
||||
}
|
||||
50
backend/vendor/doctrine/orm/src/Cache/EntityCacheEntry.php
vendored
Normal file
50
backend/vendor/doctrine/orm/src/Cache/EntityCacheEntry.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use function array_map;
|
||||
|
||||
class EntityCacheEntry implements CacheEntry
|
||||
{
|
||||
/**
|
||||
* @param class-string $class The entity class name
|
||||
* @param array<string,mixed> $data The entity map data
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $class,
|
||||
public readonly array $data,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new EntityCacheEntry
|
||||
*
|
||||
* This method allows Doctrine\Common\Cache\PhpFileCache compatibility
|
||||
*
|
||||
* @param array<string,mixed> $values array containing property values
|
||||
*/
|
||||
public static function __set_state(array $values): self
|
||||
{
|
||||
return new self($values['class'], $values['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the entity data resolving cache entries
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function resolveAssociationEntries(EntityManagerInterface $em): array
|
||||
{
|
||||
return array_map(static function ($value) use ($em) {
|
||||
if (! ($value instanceof AssociationCacheEntry)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return $em->getReference($value->class, $value->identifier);
|
||||
}, $this->data);
|
||||
}
|
||||
}
|
||||
38
backend/vendor/doctrine/orm/src/Cache/EntityCacheKey.php
vendored
Normal file
38
backend/vendor/doctrine/orm/src/Cache/EntityCacheKey.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use function implode;
|
||||
use function ksort;
|
||||
use function str_replace;
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
* Defines entity classes roles to be stored in the cache region.
|
||||
*/
|
||||
class EntityCacheKey extends CacheKey
|
||||
{
|
||||
/**
|
||||
* The entity identifier
|
||||
*
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
public readonly array $identifier;
|
||||
|
||||
/**
|
||||
* @param class-string $entityClass The entity class name. In a inheritance hierarchy it should always be the root entity class.
|
||||
* @param array<string, mixed> $identifier The entity identifier
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $entityClass,
|
||||
array $identifier,
|
||||
) {
|
||||
ksort($identifier);
|
||||
|
||||
$this->identifier = $identifier;
|
||||
|
||||
parent::__construct(str_replace('\\', '.', strtolower($entityClass) . '_' . implode(' ', $identifier)));
|
||||
}
|
||||
}
|
||||
28
backend/vendor/doctrine/orm/src/Cache/EntityHydrator.php
vendored
Normal file
28
backend/vendor/doctrine/orm/src/Cache/EntityHydrator.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
|
||||
/**
|
||||
* Hydrator cache entry for entities
|
||||
*/
|
||||
interface EntityHydrator
|
||||
{
|
||||
/**
|
||||
* @param ClassMetadata $metadata The entity metadata.
|
||||
* @param EntityCacheKey $key The entity cache key.
|
||||
* @param object $entity The entity.
|
||||
*/
|
||||
public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, object $entity): EntityCacheEntry;
|
||||
|
||||
/**
|
||||
* @param ClassMetadata $metadata The entity metadata.
|
||||
* @param EntityCacheKey $key The entity cache key.
|
||||
* @param EntityCacheEntry $entry The entity cache entry.
|
||||
* @param object|null $entity The entity to load the cache into. If not specified, a new entity is created.
|
||||
*/
|
||||
public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, object|null $entity = null): object|null;
|
||||
}
|
||||
14
backend/vendor/doctrine/orm/src/Cache/Exception/CacheException.php
vendored
Normal file
14
backend/vendor/doctrine/orm/src/Cache/Exception/CacheException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Exception;
|
||||
|
||||
use Doctrine\ORM\Cache\CacheException as BaseCacheException;
|
||||
|
||||
/**
|
||||
* Exception for cache.
|
||||
*/
|
||||
class CacheException extends BaseCacheException
|
||||
{
|
||||
}
|
||||
19
backend/vendor/doctrine/orm/src/Cache/Exception/CannotUpdateReadOnlyCollection.php
vendored
Normal file
19
backend/vendor/doctrine/orm/src/Cache/Exception/CannotUpdateReadOnlyCollection.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Exception;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class CannotUpdateReadOnlyCollection extends CacheException
|
||||
{
|
||||
public static function fromEntityAndField(string $sourceEntity, string $fieldName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Cannot update a readonly collection "%s#%s"',
|
||||
$sourceEntity,
|
||||
$fieldName,
|
||||
));
|
||||
}
|
||||
}
|
||||
15
backend/vendor/doctrine/orm/src/Cache/Exception/CannotUpdateReadOnlyEntity.php
vendored
Normal file
15
backend/vendor/doctrine/orm/src/Cache/Exception/CannotUpdateReadOnlyEntity.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Exception;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class CannotUpdateReadOnlyEntity extends CacheException
|
||||
{
|
||||
public static function fromEntity(string $entityName): self
|
||||
{
|
||||
return new self(sprintf('Cannot update a readonly entity "%s"', $entityName));
|
||||
}
|
||||
}
|
||||
28
backend/vendor/doctrine/orm/src/Cache/Exception/FeatureNotImplemented.php
vendored
Normal file
28
backend/vendor/doctrine/orm/src/Cache/Exception/FeatureNotImplemented.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Exception;
|
||||
|
||||
class FeatureNotImplemented extends CacheException
|
||||
{
|
||||
public static function scalarResults(): self
|
||||
{
|
||||
return new self('Second level cache does not support scalar results.');
|
||||
}
|
||||
|
||||
public static function multipleRootEntities(): self
|
||||
{
|
||||
return new self('Second level cache does not support multiple root entities.');
|
||||
}
|
||||
|
||||
public static function nonSelectStatements(): self
|
||||
{
|
||||
return new self('Second-level cache query supports only select statements.');
|
||||
}
|
||||
|
||||
public static function partialEntities(): self
|
||||
{
|
||||
return new self('Second level cache does not support partial entities.');
|
||||
}
|
||||
}
|
||||
18
backend/vendor/doctrine/orm/src/Cache/Exception/NonCacheableEntity.php
vendored
Normal file
18
backend/vendor/doctrine/orm/src/Cache/Exception/NonCacheableEntity.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Exception;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class NonCacheableEntity extends CacheException
|
||||
{
|
||||
public static function fromEntity(string $entityName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Entity "%s" not configured as part of the second-level cache.',
|
||||
$entityName,
|
||||
));
|
||||
}
|
||||
}
|
||||
19
backend/vendor/doctrine/orm/src/Cache/Exception/NonCacheableEntityAssociation.php
vendored
Normal file
19
backend/vendor/doctrine/orm/src/Cache/Exception/NonCacheableEntityAssociation.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Exception;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class NonCacheableEntityAssociation extends CacheException
|
||||
{
|
||||
public static function fromEntityAndField(string $entityName, string $field): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Entity association field "%s#%s" not configured as part of the second-level cache.',
|
||||
$entityName,
|
||||
$field,
|
||||
));
|
||||
}
|
||||
}
|
||||
25
backend/vendor/doctrine/orm/src/Cache/Lock.php
vendored
Normal file
25
backend/vendor/doctrine/orm/src/Cache/Lock.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use function time;
|
||||
use function uniqid;
|
||||
|
||||
class Lock
|
||||
{
|
||||
public int $time;
|
||||
|
||||
public function __construct(
|
||||
public string $value,
|
||||
int|null $time = null,
|
||||
) {
|
||||
$this->time = $time ?? time();
|
||||
}
|
||||
|
||||
public static function createLockRead(): Lock
|
||||
{
|
||||
return new self(uniqid((string) time(), true));
|
||||
}
|
||||
}
|
||||
14
backend/vendor/doctrine/orm/src/Cache/LockException.php
vendored
Normal file
14
backend/vendor/doctrine/orm/src/Cache/LockException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Cache\Exception\CacheException;
|
||||
|
||||
/**
|
||||
* Lock exception for cache.
|
||||
*/
|
||||
class LockException extends CacheException
|
||||
{
|
||||
}
|
||||
60
backend/vendor/doctrine/orm/src/Cache/Logging/CacheLogger.php
vendored
Normal file
60
backend/vendor/doctrine/orm/src/Cache/Logging/CacheLogger.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Logging;
|
||||
|
||||
use Doctrine\ORM\Cache\CollectionCacheKey;
|
||||
use Doctrine\ORM\Cache\EntityCacheKey;
|
||||
use Doctrine\ORM\Cache\QueryCacheKey;
|
||||
|
||||
/**
|
||||
* Interface for logging.
|
||||
*/
|
||||
interface CacheLogger
|
||||
{
|
||||
/**
|
||||
* Log an entity put into second level cache.
|
||||
*/
|
||||
public function entityCachePut(string $regionName, EntityCacheKey $key): void;
|
||||
|
||||
/**
|
||||
* Log an entity get from second level cache resulted in a hit.
|
||||
*/
|
||||
public function entityCacheHit(string $regionName, EntityCacheKey $key): void;
|
||||
|
||||
/**
|
||||
* Log an entity get from second level cache resulted in a miss.
|
||||
*/
|
||||
public function entityCacheMiss(string $regionName, EntityCacheKey $key): void;
|
||||
|
||||
/**
|
||||
* Log an entity put into second level cache.
|
||||
*/
|
||||
public function collectionCachePut(string $regionName, CollectionCacheKey $key): void;
|
||||
|
||||
/**
|
||||
* Log an entity get from second level cache resulted in a hit.
|
||||
*/
|
||||
public function collectionCacheHit(string $regionName, CollectionCacheKey $key): void;
|
||||
|
||||
/**
|
||||
* Log an entity get from second level cache resulted in a miss.
|
||||
*/
|
||||
public function collectionCacheMiss(string $regionName, CollectionCacheKey $key): void;
|
||||
|
||||
/**
|
||||
* Log a query put into the query cache.
|
||||
*/
|
||||
public function queryCachePut(string $regionName, QueryCacheKey $key): void;
|
||||
|
||||
/**
|
||||
* Log a query get from the query cache resulted in a hit.
|
||||
*/
|
||||
public function queryCacheHit(string $regionName, QueryCacheKey $key): void;
|
||||
|
||||
/**
|
||||
* Log a query get from the query cache resulted in a miss.
|
||||
*/
|
||||
public function queryCacheMiss(string $regionName, QueryCacheKey $key): void;
|
||||
}
|
||||
94
backend/vendor/doctrine/orm/src/Cache/Logging/CacheLoggerChain.php
vendored
Normal file
94
backend/vendor/doctrine/orm/src/Cache/Logging/CacheLoggerChain.php
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Logging;
|
||||
|
||||
use Doctrine\ORM\Cache\CollectionCacheKey;
|
||||
use Doctrine\ORM\Cache\EntityCacheKey;
|
||||
use Doctrine\ORM\Cache\QueryCacheKey;
|
||||
|
||||
class CacheLoggerChain implements CacheLogger
|
||||
{
|
||||
/** @var array<string, CacheLogger> */
|
||||
private array $loggers = [];
|
||||
|
||||
public function setLogger(string $name, CacheLogger $logger): void
|
||||
{
|
||||
$this->loggers[$name] = $logger;
|
||||
}
|
||||
|
||||
public function getLogger(string $name): CacheLogger|null
|
||||
{
|
||||
return $this->loggers[$name] ?? null;
|
||||
}
|
||||
|
||||
/** @return array<string, CacheLogger> */
|
||||
public function getLoggers(): array
|
||||
{
|
||||
return $this->loggers;
|
||||
}
|
||||
|
||||
public function collectionCacheHit(string $regionName, CollectionCacheKey $key): void
|
||||
{
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->collectionCacheHit($regionName, $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function collectionCacheMiss(string $regionName, CollectionCacheKey $key): void
|
||||
{
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->collectionCacheMiss($regionName, $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function collectionCachePut(string $regionName, CollectionCacheKey $key): void
|
||||
{
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->collectionCachePut($regionName, $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function entityCacheHit(string $regionName, EntityCacheKey $key): void
|
||||
{
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->entityCacheHit($regionName, $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function entityCacheMiss(string $regionName, EntityCacheKey $key): void
|
||||
{
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->entityCacheMiss($regionName, $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function entityCachePut(string $regionName, EntityCacheKey $key): void
|
||||
{
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->entityCachePut($regionName, $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function queryCacheHit(string $regionName, QueryCacheKey $key): void
|
||||
{
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->queryCacheHit($regionName, $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function queryCacheMiss(string $regionName, QueryCacheKey $key): void
|
||||
{
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->queryCacheMiss($regionName, $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function queryCachePut(string $regionName, QueryCacheKey $key): void
|
||||
{
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->queryCachePut($regionName, $key);
|
||||
}
|
||||
}
|
||||
}
|
||||
174
backend/vendor/doctrine/orm/src/Cache/Logging/StatisticsCacheLogger.php
vendored
Normal file
174
backend/vendor/doctrine/orm/src/Cache/Logging/StatisticsCacheLogger.php
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Logging;
|
||||
|
||||
use Doctrine\ORM\Cache\CollectionCacheKey;
|
||||
use Doctrine\ORM\Cache\EntityCacheKey;
|
||||
use Doctrine\ORM\Cache\QueryCacheKey;
|
||||
|
||||
use function array_sum;
|
||||
|
||||
/**
|
||||
* Provide basic second level cache statistics.
|
||||
*/
|
||||
class StatisticsCacheLogger implements CacheLogger
|
||||
{
|
||||
/** @var array<string, int> */
|
||||
private array $cacheMissCountMap = [];
|
||||
|
||||
/** @var array<string, int> */
|
||||
private array $cacheHitCountMap = [];
|
||||
|
||||
/** @var array<string, int> */
|
||||
private array $cachePutCountMap = [];
|
||||
|
||||
public function collectionCacheMiss(string $regionName, CollectionCacheKey $key): void
|
||||
{
|
||||
$this->cacheMissCountMap[$regionName]
|
||||
= ($this->cacheMissCountMap[$regionName] ?? 0) + 1;
|
||||
}
|
||||
|
||||
public function collectionCacheHit(string $regionName, CollectionCacheKey $key): void
|
||||
{
|
||||
$this->cacheHitCountMap[$regionName]
|
||||
= ($this->cacheHitCountMap[$regionName] ?? 0) + 1;
|
||||
}
|
||||
|
||||
public function collectionCachePut(string $regionName, CollectionCacheKey $key): void
|
||||
{
|
||||
$this->cachePutCountMap[$regionName]
|
||||
= ($this->cachePutCountMap[$regionName] ?? 0) + 1;
|
||||
}
|
||||
|
||||
public function entityCacheMiss(string $regionName, EntityCacheKey $key): void
|
||||
{
|
||||
$this->cacheMissCountMap[$regionName]
|
||||
= ($this->cacheMissCountMap[$regionName] ?? 0) + 1;
|
||||
}
|
||||
|
||||
public function entityCacheHit(string $regionName, EntityCacheKey $key): void
|
||||
{
|
||||
$this->cacheHitCountMap[$regionName]
|
||||
= ($this->cacheHitCountMap[$regionName] ?? 0) + 1;
|
||||
}
|
||||
|
||||
public function entityCachePut(string $regionName, EntityCacheKey $key): void
|
||||
{
|
||||
$this->cachePutCountMap[$regionName]
|
||||
= ($this->cachePutCountMap[$regionName] ?? 0) + 1;
|
||||
}
|
||||
|
||||
public function queryCacheHit(string $regionName, QueryCacheKey $key): void
|
||||
{
|
||||
$this->cacheHitCountMap[$regionName]
|
||||
= ($this->cacheHitCountMap[$regionName] ?? 0) + 1;
|
||||
}
|
||||
|
||||
public function queryCacheMiss(string $regionName, QueryCacheKey $key): void
|
||||
{
|
||||
$this->cacheMissCountMap[$regionName]
|
||||
= ($this->cacheMissCountMap[$regionName] ?? 0) + 1;
|
||||
}
|
||||
|
||||
public function queryCachePut(string $regionName, QueryCacheKey $key): void
|
||||
{
|
||||
$this->cachePutCountMap[$regionName]
|
||||
= ($this->cachePutCountMap[$regionName] ?? 0) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of entries successfully retrieved from cache.
|
||||
*
|
||||
* @param string $regionName The name of the cache region.
|
||||
*/
|
||||
public function getRegionHitCount(string $regionName): int
|
||||
{
|
||||
return $this->cacheHitCountMap[$regionName] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of cached entries *not* found in cache.
|
||||
*
|
||||
* @param string $regionName The name of the cache region.
|
||||
*/
|
||||
public function getRegionMissCount(string $regionName): int
|
||||
{
|
||||
return $this->cacheMissCountMap[$regionName] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of cacheable entries put in cache.
|
||||
*
|
||||
* @param string $regionName The name of the cache region.
|
||||
*/
|
||||
public function getRegionPutCount(string $regionName): int
|
||||
{
|
||||
return $this->cachePutCountMap[$regionName] ?? 0;
|
||||
}
|
||||
|
||||
/** @return array<string, int> */
|
||||
public function getRegionsMiss(): array
|
||||
{
|
||||
return $this->cacheMissCountMap;
|
||||
}
|
||||
|
||||
/** @return array<string, int> */
|
||||
public function getRegionsHit(): array
|
||||
{
|
||||
return $this->cacheHitCountMap;
|
||||
}
|
||||
|
||||
/** @return array<string, int> */
|
||||
public function getRegionsPut(): array
|
||||
{
|
||||
return $this->cachePutCountMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear region statistics
|
||||
*
|
||||
* @param string $regionName The name of the cache region.
|
||||
*/
|
||||
public function clearRegionStats(string $regionName): void
|
||||
{
|
||||
$this->cachePutCountMap[$regionName] = 0;
|
||||
$this->cacheHitCountMap[$regionName] = 0;
|
||||
$this->cacheMissCountMap[$regionName] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all statistics
|
||||
*/
|
||||
public function clearStats(): void
|
||||
{
|
||||
$this->cachePutCountMap = [];
|
||||
$this->cacheHitCountMap = [];
|
||||
$this->cacheMissCountMap = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of put in cache.
|
||||
*/
|
||||
public function getPutCount(): int
|
||||
{
|
||||
return array_sum($this->cachePutCountMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of entries successfully retrieved from cache.
|
||||
*/
|
||||
public function getHitCount(): int
|
||||
{
|
||||
return array_sum($this->cacheHitCountMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of cached entries *not* found in cache.
|
||||
*/
|
||||
public function getMissCount(): int
|
||||
{
|
||||
return array_sum($this->cacheMissCountMap);
|
||||
}
|
||||
}
|
||||
25
backend/vendor/doctrine/orm/src/Cache/Persister/CachedPersister.php
vendored
Normal file
25
backend/vendor/doctrine/orm/src/Cache/Persister/CachedPersister.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister;
|
||||
|
||||
use Doctrine\ORM\Cache\Region;
|
||||
|
||||
/**
|
||||
* Interface for persister that support second level cache.
|
||||
*/
|
||||
interface CachedPersister
|
||||
{
|
||||
/**
|
||||
* Perform whatever processing is encapsulated here after completion of the transaction.
|
||||
*/
|
||||
public function afterTransactionComplete(): void;
|
||||
|
||||
/**
|
||||
* Perform whatever processing is encapsulated here after completion of the rolled-back.
|
||||
*/
|
||||
public function afterTransactionRolledBack(): void;
|
||||
|
||||
public function getCacheRegion(): Region;
|
||||
}
|
||||
174
backend/vendor/doctrine/orm/src/Cache/Persister/Collection/AbstractCollectionPersister.php
vendored
Normal file
174
backend/vendor/doctrine/orm/src/Cache/Persister/Collection/AbstractCollectionPersister.php
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Collection;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\ORM\Cache\CollectionCacheKey;
|
||||
use Doctrine\ORM\Cache\CollectionHydrator;
|
||||
use Doctrine\ORM\Cache\Logging\CacheLogger;
|
||||
use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister;
|
||||
use Doctrine\ORM\Cache\Region;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\AssociationMapping;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\ORM\Query\FilterCollection;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
use function array_values;
|
||||
use function assert;
|
||||
use function count;
|
||||
|
||||
abstract class AbstractCollectionPersister implements CachedCollectionPersister
|
||||
{
|
||||
protected UnitOfWork $uow;
|
||||
protected ClassMetadataFactory $metadataFactory;
|
||||
protected ClassMetadata $sourceEntity;
|
||||
protected ClassMetadata $targetEntity;
|
||||
|
||||
/** @var mixed[] */
|
||||
protected array $queuedCache = [];
|
||||
|
||||
protected string $regionName;
|
||||
protected FilterCollection $filters;
|
||||
protected CollectionHydrator $hydrator;
|
||||
protected CacheLogger|null $cacheLogger;
|
||||
|
||||
public function __construct(
|
||||
protected CollectionPersister $persister,
|
||||
protected Region $region,
|
||||
EntityManagerInterface $em,
|
||||
protected AssociationMapping $association,
|
||||
) {
|
||||
$configuration = $em->getConfiguration();
|
||||
$cacheConfig = $configuration->getSecondLevelCacheConfiguration();
|
||||
$cacheFactory = $cacheConfig->getCacheFactory();
|
||||
|
||||
$this->region = $region;
|
||||
$this->persister = $persister;
|
||||
$this->association = $association;
|
||||
$this->filters = $em->getFilters();
|
||||
$this->regionName = $region->getName();
|
||||
$this->uow = $em->getUnitOfWork();
|
||||
$this->metadataFactory = $em->getMetadataFactory();
|
||||
$this->cacheLogger = $cacheConfig->getCacheLogger();
|
||||
$this->hydrator = $cacheFactory->buildCollectionHydrator($em, $association);
|
||||
$this->sourceEntity = $em->getClassMetadata($association->sourceEntity);
|
||||
$this->targetEntity = $em->getClassMetadata($association->targetEntity);
|
||||
}
|
||||
|
||||
public function getCacheRegion(): Region
|
||||
{
|
||||
return $this->region;
|
||||
}
|
||||
|
||||
public function getSourceEntityMetadata(): ClassMetadata
|
||||
{
|
||||
return $this->sourceEntity;
|
||||
}
|
||||
|
||||
public function getTargetEntityMetadata(): ClassMetadata
|
||||
{
|
||||
return $this->targetEntity;
|
||||
}
|
||||
|
||||
public function loadCollectionCache(PersistentCollection $collection, CollectionCacheKey $key): array|null
|
||||
{
|
||||
$cache = $this->region->get($key);
|
||||
|
||||
if ($cache === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->hydrator->loadCacheEntry($this->sourceEntity, $key, $cache, $collection);
|
||||
}
|
||||
|
||||
public function storeCollectionCache(CollectionCacheKey $key, Collection|array $elements): void
|
||||
{
|
||||
$associationMapping = $this->sourceEntity->associationMappings[$key->association];
|
||||
$targetPersister = $this->uow->getEntityPersister($this->targetEntity->rootEntityName);
|
||||
assert($targetPersister instanceof CachedEntityPersister);
|
||||
$targetRegion = $targetPersister->getCacheRegion();
|
||||
$targetHydrator = $targetPersister->getEntityHydrator();
|
||||
|
||||
// Only preserve ordering if association configured it
|
||||
if (! $associationMapping->isIndexed()) {
|
||||
// Elements may be an array or a Collection
|
||||
$elements = array_values($elements instanceof Collection ? $elements->getValues() : $elements);
|
||||
}
|
||||
|
||||
$entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements);
|
||||
|
||||
foreach ($entry->identifiers as $index => $entityKey) {
|
||||
if ($targetRegion->contains($entityKey)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$class = $this->targetEntity;
|
||||
$className = DefaultProxyClassNameResolver::getClass($elements[$index]);
|
||||
|
||||
if ($className !== $this->targetEntity->name) {
|
||||
$class = $this->metadataFactory->getMetadataFor($className);
|
||||
}
|
||||
|
||||
$entity = $elements[$index];
|
||||
$entityEntry = $targetHydrator->buildCacheEntry($class, $entityKey, $entity);
|
||||
|
||||
$targetRegion->put($entityKey, $entityEntry);
|
||||
}
|
||||
|
||||
if ($this->region->put($key, $entry)) {
|
||||
$this->cacheLogger?->collectionCachePut($this->regionName, $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function contains(PersistentCollection $collection, object $element): bool
|
||||
{
|
||||
return $this->persister->contains($collection, $element);
|
||||
}
|
||||
|
||||
public function containsKey(PersistentCollection $collection, mixed $key): bool
|
||||
{
|
||||
return $this->persister->containsKey($collection, $key);
|
||||
}
|
||||
|
||||
public function count(PersistentCollection $collection): int
|
||||
{
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
$entry = $this->region->get($key);
|
||||
|
||||
if ($entry !== null) {
|
||||
return count($entry->identifiers);
|
||||
}
|
||||
|
||||
return $this->persister->count($collection);
|
||||
}
|
||||
|
||||
public function get(PersistentCollection $collection, mixed $index): mixed
|
||||
{
|
||||
return $this->persister->get($collection, $index);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function slice(PersistentCollection $collection, int $offset, int|null $length = null): array
|
||||
{
|
||||
return $this->persister->slice($collection, $offset, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadCriteria(PersistentCollection $collection, Criteria $criteria): array
|
||||
{
|
||||
return $this->persister->loadCriteria($collection, $criteria);
|
||||
}
|
||||
}
|
||||
36
backend/vendor/doctrine/orm/src/Cache/Persister/Collection/CachedCollectionPersister.php
vendored
Normal file
36
backend/vendor/doctrine/orm/src/Cache/Persister/Collection/CachedCollectionPersister.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Collection;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Cache\CollectionCacheKey;
|
||||
use Doctrine\ORM\Cache\Persister\CachedPersister;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
|
||||
|
||||
/**
|
||||
* Interface for second level cache collection persisters.
|
||||
*/
|
||||
interface CachedCollectionPersister extends CachedPersister, CollectionPersister
|
||||
{
|
||||
public function getSourceEntityMetadata(): ClassMetadata;
|
||||
|
||||
public function getTargetEntityMetadata(): ClassMetadata;
|
||||
|
||||
/**
|
||||
* Loads a collection from cache
|
||||
*
|
||||
* @return mixed[]|null
|
||||
*/
|
||||
public function loadCollectionCache(PersistentCollection $collection, CollectionCacheKey $key): array|null;
|
||||
|
||||
/**
|
||||
* Stores a collection into cache
|
||||
*
|
||||
* @param mixed[]|Collection $elements
|
||||
*/
|
||||
public function storeCollectionCache(CollectionCacheKey $key, Collection|array $elements): void;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Collection;
|
||||
|
||||
use Doctrine\ORM\Cache\CollectionCacheKey;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
|
||||
use function spl_object_id;
|
||||
|
||||
class NonStrictReadWriteCachedCollectionPersister extends AbstractCollectionPersister
|
||||
{
|
||||
public function afterTransactionComplete(): void
|
||||
{
|
||||
if (isset($this->queuedCache['update'])) {
|
||||
foreach ($this->queuedCache['update'] as $item) {
|
||||
$this->storeCollectionCache($item['key'], $item['list']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->queuedCache['delete'])) {
|
||||
foreach ($this->queuedCache['delete'] as $key) {
|
||||
$this->region->evict($key);
|
||||
}
|
||||
}
|
||||
|
||||
$this->queuedCache = [];
|
||||
}
|
||||
|
||||
public function afterTransactionRolledBack(): void
|
||||
{
|
||||
$this->queuedCache = [];
|
||||
}
|
||||
|
||||
public function delete(PersistentCollection $collection): void
|
||||
{
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
|
||||
$this->persister->delete($collection);
|
||||
|
||||
$this->queuedCache['delete'][spl_object_id($collection)] = $key;
|
||||
}
|
||||
|
||||
public function update(PersistentCollection $collection): void
|
||||
{
|
||||
$isInitialized = $collection->isInitialized();
|
||||
$isDirty = $collection->isDirty();
|
||||
|
||||
if (! $isInitialized && ! $isDirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
|
||||
// Invalidate non initialized collections OR ordered collection
|
||||
if ($isDirty && ! $isInitialized || $this->association->isOrdered()) {
|
||||
$this->persister->update($collection);
|
||||
|
||||
$this->queuedCache['delete'][spl_object_id($collection)] = $key;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->persister->update($collection);
|
||||
|
||||
$this->queuedCache['update'][spl_object_id($collection)] = [
|
||||
'key' => $key,
|
||||
'list' => $collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
24
backend/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php
vendored
Normal file
24
backend/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Collection;
|
||||
|
||||
use Doctrine\ORM\Cache\Exception\CannotUpdateReadOnlyCollection;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
|
||||
class ReadOnlyCachedCollectionPersister extends NonStrictReadWriteCachedCollectionPersister
|
||||
{
|
||||
public function update(PersistentCollection $collection): void
|
||||
{
|
||||
if ($collection->isDirty() && $collection->getSnapshot()) {
|
||||
throw CannotUpdateReadOnlyCollection::fromEntityAndField(
|
||||
DefaultProxyClassNameResolver::getClass($collection->getOwner()),
|
||||
$this->association->fieldName,
|
||||
);
|
||||
}
|
||||
|
||||
parent::update($collection);
|
||||
}
|
||||
}
|
||||
103
backend/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php
vendored
Normal file
103
backend/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Collection;
|
||||
|
||||
use Doctrine\ORM\Cache\CollectionCacheKey;
|
||||
use Doctrine\ORM\Cache\ConcurrentRegion;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\AssociationMapping;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
|
||||
|
||||
use function spl_object_id;
|
||||
|
||||
class ReadWriteCachedCollectionPersister extends AbstractCollectionPersister
|
||||
{
|
||||
public function __construct(
|
||||
CollectionPersister $persister,
|
||||
ConcurrentRegion $region,
|
||||
EntityManagerInterface $em,
|
||||
AssociationMapping $association,
|
||||
) {
|
||||
parent::__construct($persister, $region, $em, $association);
|
||||
}
|
||||
|
||||
public function afterTransactionComplete(): void
|
||||
{
|
||||
if (isset($this->queuedCache['update'])) {
|
||||
foreach ($this->queuedCache['update'] as $item) {
|
||||
$this->region->evict($item['key']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->queuedCache['delete'])) {
|
||||
foreach ($this->queuedCache['delete'] as $item) {
|
||||
$this->region->evict($item['key']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->queuedCache = [];
|
||||
}
|
||||
|
||||
public function afterTransactionRolledBack(): void
|
||||
{
|
||||
if (isset($this->queuedCache['update'])) {
|
||||
foreach ($this->queuedCache['update'] as $item) {
|
||||
$this->region->evict($item['key']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->queuedCache['delete'])) {
|
||||
foreach ($this->queuedCache['delete'] as $item) {
|
||||
$this->region->evict($item['key']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->queuedCache = [];
|
||||
}
|
||||
|
||||
public function delete(PersistentCollection $collection): void
|
||||
{
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
$lock = $this->region->lock($key);
|
||||
|
||||
$this->persister->delete($collection);
|
||||
|
||||
if ($lock === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->queuedCache['delete'][spl_object_id($collection)] = [
|
||||
'key' => $key,
|
||||
'lock' => $lock,
|
||||
];
|
||||
}
|
||||
|
||||
public function update(PersistentCollection $collection): void
|
||||
{
|
||||
$isInitialized = $collection->isInitialized();
|
||||
$isDirty = $collection->isDirty();
|
||||
|
||||
if (! $isInitialized && ! $isDirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->persister->update($collection);
|
||||
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
$lock = $this->region->lock($key);
|
||||
|
||||
if ($lock === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->queuedCache['update'][spl_object_id($collection)] = [
|
||||
'key' => $key,
|
||||
'lock' => $lock,
|
||||
];
|
||||
}
|
||||
}
|
||||
564
backend/vendor/doctrine/orm/src/Cache/Persister/Entity/AbstractEntityPersister.php
vendored
Normal file
564
backend/vendor/doctrine/orm/src/Cache/Persister/Entity/AbstractEntityPersister.php
vendored
Normal file
@@ -0,0 +1,564 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\Common\Collections\Order;
|
||||
use Doctrine\DBAL\LockMode;
|
||||
use Doctrine\ORM\Cache;
|
||||
use Doctrine\ORM\Cache\CollectionCacheKey;
|
||||
use Doctrine\ORM\Cache\EntityCacheKey;
|
||||
use Doctrine\ORM\Cache\EntityHydrator;
|
||||
use Doctrine\ORM\Cache\Logging\CacheLogger;
|
||||
use Doctrine\ORM\Cache\Persister\CachedPersister;
|
||||
use Doctrine\ORM\Cache\QueryCacheKey;
|
||||
use Doctrine\ORM\Cache\Region;
|
||||
use Doctrine\ORM\Cache\TimestampCacheKey;
|
||||
use Doctrine\ORM\Cache\TimestampRegion;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\AssociationMapping;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\Persisters\Entity\EntityPersister;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\ORM\Query\FilterCollection;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
use function array_merge;
|
||||
use function func_get_args;
|
||||
use function serialize;
|
||||
use function sha1;
|
||||
|
||||
abstract class AbstractEntityPersister implements CachedEntityPersister
|
||||
{
|
||||
protected UnitOfWork $uow;
|
||||
protected ClassMetadataFactory $metadataFactory;
|
||||
|
||||
/** @var mixed[] */
|
||||
protected array $queuedCache = [];
|
||||
|
||||
protected TimestampRegion $timestampRegion;
|
||||
protected TimestampCacheKey $timestampKey;
|
||||
protected EntityHydrator $hydrator;
|
||||
protected Cache $cache;
|
||||
protected FilterCollection $filters;
|
||||
protected CacheLogger|null $cacheLogger = null;
|
||||
protected string $regionName;
|
||||
|
||||
/**
|
||||
* Associations configured as FETCH_EAGER, as well as all inverse one-to-one associations.
|
||||
*
|
||||
* @var array<string>|null
|
||||
*/
|
||||
protected array|null $joinedAssociations = null;
|
||||
|
||||
public function __construct(
|
||||
protected EntityPersister $persister,
|
||||
protected Region $region,
|
||||
EntityManagerInterface $em,
|
||||
protected ClassMetadata $class,
|
||||
) {
|
||||
$configuration = $em->getConfiguration();
|
||||
$cacheConfig = $configuration->getSecondLevelCacheConfiguration();
|
||||
$cacheFactory = $cacheConfig->getCacheFactory();
|
||||
|
||||
$this->cache = $em->getCache();
|
||||
$this->filters = $em->getFilters();
|
||||
$this->regionName = $region->getName();
|
||||
$this->uow = $em->getUnitOfWork();
|
||||
$this->metadataFactory = $em->getMetadataFactory();
|
||||
$this->cacheLogger = $cacheConfig->getCacheLogger();
|
||||
$this->timestampRegion = $cacheFactory->getTimestampRegion();
|
||||
$this->hydrator = $cacheFactory->buildEntityHydrator($em, $class);
|
||||
$this->timestampKey = new TimestampCacheKey($this->class->rootEntityName);
|
||||
}
|
||||
|
||||
public function addInsert(object $entity): void
|
||||
{
|
||||
$this->persister->addInsert($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getInserts(): array
|
||||
{
|
||||
return $this->persister->getInserts();
|
||||
}
|
||||
|
||||
public function getSelectSQL(
|
||||
array|Criteria $criteria,
|
||||
AssociationMapping|null $assoc = null,
|
||||
LockMode|int|null $lockMode = null,
|
||||
int|null $limit = null,
|
||||
int|null $offset = null,
|
||||
array|null $orderBy = null,
|
||||
): string {
|
||||
return $this->persister->getSelectSQL($criteria, $assoc, $lockMode, $limit, $offset, $orderBy);
|
||||
}
|
||||
|
||||
public function getCountSQL(array|Criteria $criteria = []): string
|
||||
{
|
||||
return $this->persister->getCountSQL($criteria);
|
||||
}
|
||||
|
||||
public function getInsertSQL(): string
|
||||
{
|
||||
return $this->persister->getInsertSQL();
|
||||
}
|
||||
|
||||
public function getResultSetMapping(): ResultSetMapping
|
||||
{
|
||||
return $this->persister->getResultSetMapping();
|
||||
}
|
||||
|
||||
public function getSelectConditionStatementSQL(
|
||||
string $field,
|
||||
mixed $value,
|
||||
AssociationMapping|null $assoc = null,
|
||||
string|null $comparison = null,
|
||||
): string {
|
||||
return $this->persister->getSelectConditionStatementSQL($field, $value, $assoc, $comparison);
|
||||
}
|
||||
|
||||
public function exists(object $entity, Criteria|null $extraConditions = null): bool
|
||||
{
|
||||
if ($extraConditions === null) {
|
||||
$key = new EntityCacheKey($this->class->rootEntityName, $this->class->getIdentifierValues($entity));
|
||||
|
||||
if ($this->region->contains($key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->persister->exists($entity, $extraConditions);
|
||||
}
|
||||
|
||||
public function getCacheRegion(): Region
|
||||
{
|
||||
return $this->region;
|
||||
}
|
||||
|
||||
public function getEntityHydrator(): EntityHydrator
|
||||
{
|
||||
return $this->hydrator;
|
||||
}
|
||||
|
||||
public function storeEntityCache(object $entity, EntityCacheKey $key): bool
|
||||
{
|
||||
$class = $this->class;
|
||||
$className = DefaultProxyClassNameResolver::getClass($entity);
|
||||
|
||||
if ($className !== $this->class->name) {
|
||||
$class = $this->metadataFactory->getMetadataFor($className);
|
||||
}
|
||||
|
||||
$entry = $this->hydrator->buildCacheEntry($class, $key, $entity);
|
||||
$cached = $this->region->put($key, $entry);
|
||||
|
||||
if ($cached) {
|
||||
$this->cacheLogger?->entityCachePut($this->regionName, $key);
|
||||
}
|
||||
|
||||
return $cached;
|
||||
}
|
||||
|
||||
private function storeJoinedAssociations(object $entity): void
|
||||
{
|
||||
if ($this->joinedAssociations === null) {
|
||||
$associations = [];
|
||||
|
||||
foreach ($this->class->associationMappings as $name => $assoc) {
|
||||
if (
|
||||
isset($assoc->cache) &&
|
||||
($assoc->isToOne()) &&
|
||||
($assoc->fetch === ClassMetadata::FETCH_EAGER || ! $assoc->isOwningSide())
|
||||
) {
|
||||
$associations[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
$this->joinedAssociations = $associations;
|
||||
}
|
||||
|
||||
foreach ($this->joinedAssociations as $name) {
|
||||
$assoc = $this->class->associationMappings[$name];
|
||||
$assocEntity = $this->class->getFieldValue($entity, $name);
|
||||
|
||||
if ($assocEntity === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$assocId = $this->uow->getEntityIdentifier($assocEntity);
|
||||
$assocMetadata = $this->metadataFactory->getMetadataFor($assoc->targetEntity);
|
||||
$assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocId);
|
||||
$assocPersister = $this->uow->getEntityPersister($assoc->targetEntity);
|
||||
|
||||
$assocPersister->storeEntityCache($assocEntity, $assocKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string of currently query
|
||||
*
|
||||
* @param string[]|Criteria $criteria
|
||||
* @param array<string, Order>|null $orderBy
|
||||
*/
|
||||
protected function getHash(
|
||||
string $query,
|
||||
array|Criteria $criteria,
|
||||
array|null $orderBy = null,
|
||||
int|null $limit = null,
|
||||
int|null $offset = null,
|
||||
): string {
|
||||
[$params] = $criteria instanceof Criteria
|
||||
? $this->persister->expandCriteriaParameters($criteria)
|
||||
: $this->persister->expandParameters($criteria);
|
||||
|
||||
return sha1($query . serialize($params) . serialize($orderBy) . $limit . $offset . $this->filters->getHash());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function expandParameters(array $criteria): array
|
||||
{
|
||||
return $this->persister->expandParameters($criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function expandCriteriaParameters(Criteria $criteria): array
|
||||
{
|
||||
return $this->persister->expandCriteriaParameters($criteria);
|
||||
}
|
||||
|
||||
public function getClassMetadata(): ClassMetadata
|
||||
{
|
||||
return $this->persister->getClassMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getManyToManyCollection(
|
||||
AssociationMapping $assoc,
|
||||
object $sourceEntity,
|
||||
int|null $offset = null,
|
||||
int|null $limit = null,
|
||||
): array {
|
||||
return $this->persister->getManyToManyCollection($assoc, $sourceEntity, $offset, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getOneToManyCollection(
|
||||
AssociationMapping $assoc,
|
||||
object $sourceEntity,
|
||||
int|null $offset = null,
|
||||
int|null $limit = null,
|
||||
): array {
|
||||
return $this->persister->getOneToManyCollection($assoc, $sourceEntity, $offset, $limit);
|
||||
}
|
||||
|
||||
public function getOwningTable(string $fieldName): string
|
||||
{
|
||||
return $this->persister->getOwningTable($fieldName);
|
||||
}
|
||||
|
||||
public function executeInserts(): void
|
||||
{
|
||||
// The commit order/foreign key relationships may make it necessary that multiple calls to executeInsert()
|
||||
// are performed, so collect all the new entities.
|
||||
$newInserts = $this->persister->getInserts();
|
||||
|
||||
if ($newInserts) {
|
||||
$this->queuedCache['insert'] = array_merge($this->queuedCache['insert'] ?? [], $newInserts);
|
||||
}
|
||||
|
||||
$this->persister->executeInserts();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function load(
|
||||
array $criteria,
|
||||
object|null $entity = null,
|
||||
AssociationMapping|null $assoc = null,
|
||||
array $hints = [],
|
||||
LockMode|int|null $lockMode = null,
|
||||
int|null $limit = null,
|
||||
array|null $orderBy = null,
|
||||
): object|null {
|
||||
if ($entity !== null || $assoc !== null || $hints !== [] || $lockMode !== null) {
|
||||
return $this->persister->load($criteria, $entity, $assoc, $hints, $lockMode, $limit, $orderBy);
|
||||
}
|
||||
|
||||
//handle only EntityRepository#findOneBy
|
||||
$query = $this->persister->getSelectSQL($criteria, null, null, $limit, null, $orderBy);
|
||||
$hash = $this->getHash($query, $criteria);
|
||||
$rsm = $this->getResultSetMapping();
|
||||
$queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey);
|
||||
$queryCache = $this->cache->getQueryCache($this->regionName);
|
||||
$result = $queryCache->get($queryKey, $rsm);
|
||||
|
||||
if ($result !== null) {
|
||||
$this->cacheLogger?->queryCacheHit($this->regionName, $queryKey);
|
||||
|
||||
return $result[0];
|
||||
}
|
||||
|
||||
$result = $this->persister->load($criteria, $entity, $assoc, $hints, $lockMode, $limit, $orderBy);
|
||||
|
||||
if ($result === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cached = $queryCache->put($queryKey, $rsm, [$result]);
|
||||
|
||||
$this->cacheLogger?->queryCacheMiss($this->regionName, $queryKey);
|
||||
|
||||
if ($cached) {
|
||||
$this->cacheLogger?->queryCachePut($this->regionName, $queryKey);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadAll(
|
||||
array $criteria = [],
|
||||
array|null $orderBy = null,
|
||||
int|null $limit = null,
|
||||
int|null $offset = null,
|
||||
): array {
|
||||
$query = $this->persister->getSelectSQL($criteria, null, null, $limit, $offset, $orderBy);
|
||||
$hash = $this->getHash($query, $criteria);
|
||||
$rsm = $this->getResultSetMapping();
|
||||
$queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey);
|
||||
$queryCache = $this->cache->getQueryCache($this->regionName);
|
||||
$result = $queryCache->get($queryKey, $rsm);
|
||||
|
||||
if ($result !== null) {
|
||||
$this->cacheLogger?->queryCacheHit($this->regionName, $queryKey);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = $this->persister->loadAll($criteria, $orderBy, $limit, $offset);
|
||||
$cached = $queryCache->put($queryKey, $rsm, $result);
|
||||
|
||||
if ($result) {
|
||||
$this->cacheLogger?->queryCacheMiss($this->regionName, $queryKey);
|
||||
}
|
||||
|
||||
if ($cached) {
|
||||
$this->cacheLogger?->queryCachePut($this->regionName, $queryKey);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadById(array $identifier, object|null $entity = null): object|null
|
||||
{
|
||||
$cacheKey = new EntityCacheKey($this->class->rootEntityName, $identifier);
|
||||
$cacheEntry = $this->region->get($cacheKey);
|
||||
$class = $this->class;
|
||||
|
||||
if ($cacheEntry !== null) {
|
||||
if ($cacheEntry->class !== $this->class->name) {
|
||||
$class = $this->metadataFactory->getMetadataFor($cacheEntry->class);
|
||||
}
|
||||
|
||||
$cachedEntity = $this->hydrator->loadCacheEntry($class, $cacheKey, $cacheEntry, $entity);
|
||||
|
||||
if ($cachedEntity !== null) {
|
||||
$this->cacheLogger?->entityCacheHit($this->regionName, $cacheKey);
|
||||
|
||||
return $cachedEntity;
|
||||
}
|
||||
}
|
||||
|
||||
$entity = $this->persister->loadById($identifier, $entity);
|
||||
|
||||
if ($entity === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class = $this->class;
|
||||
$className = DefaultProxyClassNameResolver::getClass($entity);
|
||||
|
||||
if ($className !== $this->class->name) {
|
||||
$class = $this->metadataFactory->getMetadataFor($className);
|
||||
}
|
||||
|
||||
$cacheEntry = $this->hydrator->buildCacheEntry($class, $cacheKey, $entity);
|
||||
$cached = $this->region->put($cacheKey, $cacheEntry);
|
||||
|
||||
if ($cached && ($this->joinedAssociations === null || $this->joinedAssociations)) {
|
||||
$this->storeJoinedAssociations($entity);
|
||||
}
|
||||
|
||||
if ($cached) {
|
||||
$this->cacheLogger?->entityCachePut($this->regionName, $cacheKey);
|
||||
}
|
||||
|
||||
$this->cacheLogger?->entityCacheMiss($this->regionName, $cacheKey);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
public function count(array|Criteria $criteria = []): int
|
||||
{
|
||||
return $this->persister->count($criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadCriteria(Criteria $criteria): array
|
||||
{
|
||||
$orderBy = $criteria->orderings();
|
||||
$limit = $criteria->getMaxResults();
|
||||
$offset = $criteria->getFirstResult();
|
||||
$query = $this->persister->getSelectSQL($criteria);
|
||||
$hash = $this->getHash($query, $criteria, $orderBy, $limit, $offset);
|
||||
$rsm = $this->getResultSetMapping();
|
||||
$queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey);
|
||||
$queryCache = $this->cache->getQueryCache($this->regionName);
|
||||
$cacheResult = $queryCache->get($queryKey, $rsm);
|
||||
|
||||
if ($cacheResult !== null) {
|
||||
$this->cacheLogger?->queryCacheHit($this->regionName, $queryKey);
|
||||
|
||||
return $cacheResult;
|
||||
}
|
||||
|
||||
$result = $this->persister->loadCriteria($criteria);
|
||||
$cached = $queryCache->put($queryKey, $rsm, $result);
|
||||
|
||||
if ($result) {
|
||||
$this->cacheLogger?->queryCacheMiss($this->regionName, $queryKey);
|
||||
}
|
||||
|
||||
if ($cached) {
|
||||
$this->cacheLogger?->queryCachePut($this->regionName, $queryKey);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadManyToManyCollection(
|
||||
AssociationMapping $assoc,
|
||||
object $sourceEntity,
|
||||
PersistentCollection $collection,
|
||||
): array {
|
||||
$persister = $this->uow->getCollectionPersister($assoc);
|
||||
$hasCache = ($persister instanceof CachedPersister);
|
||||
|
||||
if (! $hasCache) {
|
||||
return $this->persister->loadManyToManyCollection($assoc, $sourceEntity, $collection);
|
||||
}
|
||||
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = $this->buildCollectionCacheKey($assoc, $ownerId, $this->filters->getHash());
|
||||
$list = $persister->loadCollectionCache($collection, $key);
|
||||
|
||||
if ($list !== null) {
|
||||
$this->cacheLogger?->collectionCacheHit($persister->getCacheRegion()->getName(), $key);
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
$list = $this->persister->loadManyToManyCollection($assoc, $sourceEntity, $collection);
|
||||
|
||||
$persister->storeCollectionCache($key, $list);
|
||||
|
||||
$this->cacheLogger?->collectionCacheMiss($persister->getCacheRegion()->getName(), $key);
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function loadOneToManyCollection(
|
||||
AssociationMapping $assoc,
|
||||
object $sourceEntity,
|
||||
PersistentCollection $collection,
|
||||
): mixed {
|
||||
$persister = $this->uow->getCollectionPersister($assoc);
|
||||
$hasCache = ($persister instanceof CachedPersister);
|
||||
|
||||
if (! $hasCache) {
|
||||
return $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $collection);
|
||||
}
|
||||
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = $this->buildCollectionCacheKey($assoc, $ownerId, $this->filters->getHash());
|
||||
$list = $persister->loadCollectionCache($collection, $key);
|
||||
|
||||
if ($list !== null) {
|
||||
$this->cacheLogger?->collectionCacheHit($persister->getCacheRegion()->getName(), $key);
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
$list = $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $collection);
|
||||
|
||||
$persister->storeCollectionCache($key, $list);
|
||||
|
||||
$this->cacheLogger?->collectionCacheMiss($persister->getCacheRegion()->getName(), $key);
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadOneToOneEntity(AssociationMapping $assoc, object $sourceEntity, array $identifier = []): object|null
|
||||
{
|
||||
return $this->persister->loadOneToOneEntity($assoc, $sourceEntity, $identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function lock(array $criteria, LockMode|int $lockMode): void
|
||||
{
|
||||
$this->persister->lock($criteria, $lockMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function refresh(array $id, object $entity, LockMode|int|null $lockMode = null): void
|
||||
{
|
||||
$this->persister->refresh($id, $entity, $lockMode);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $ownerId */
|
||||
protected function buildCollectionCacheKey(AssociationMapping $association, array $ownerId, /* string $filterHash */): CollectionCacheKey
|
||||
{
|
||||
$filterHash = (string) (func_get_args()[2] ?? ''); // todo: move to argument in next major release
|
||||
|
||||
return new CollectionCacheKey(
|
||||
$this->metadataFactory->getMetadataFor($association->sourceEntity)->rootEntityName,
|
||||
$association->fieldName,
|
||||
$ownerId,
|
||||
$filterHash,
|
||||
);
|
||||
}
|
||||
}
|
||||
20
backend/vendor/doctrine/orm/src/Cache/Persister/Entity/CachedEntityPersister.php
vendored
Normal file
20
backend/vendor/doctrine/orm/src/Cache/Persister/Entity/CachedEntityPersister.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Entity;
|
||||
|
||||
use Doctrine\ORM\Cache\EntityCacheKey;
|
||||
use Doctrine\ORM\Cache\EntityHydrator;
|
||||
use Doctrine\ORM\Cache\Persister\CachedPersister;
|
||||
use Doctrine\ORM\Persisters\Entity\EntityPersister;
|
||||
|
||||
/**
|
||||
* Interface for second level cache entity persisters.
|
||||
*/
|
||||
interface CachedEntityPersister extends CachedPersister, EntityPersister
|
||||
{
|
||||
public function getEntityHydrator(): EntityHydrator;
|
||||
|
||||
public function storeEntityCache(object $entity, EntityCacheKey $key): bool;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Entity;
|
||||
|
||||
use Doctrine\ORM\Cache\EntityCacheKey;
|
||||
|
||||
/**
|
||||
* Specific non-strict read/write cached entity persister
|
||||
*/
|
||||
class NonStrictReadWriteCachedEntityPersister extends AbstractEntityPersister
|
||||
{
|
||||
public function afterTransactionComplete(): void
|
||||
{
|
||||
$isChanged = false;
|
||||
|
||||
if (isset($this->queuedCache['insert'])) {
|
||||
foreach ($this->queuedCache['insert'] as $entity) {
|
||||
$isChanged = $this->updateCache($entity, $isChanged);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->queuedCache['update'])) {
|
||||
foreach ($this->queuedCache['update'] as $entity) {
|
||||
$isChanged = $this->updateCache($entity, $isChanged);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->queuedCache['delete'])) {
|
||||
foreach ($this->queuedCache['delete'] as $key) {
|
||||
$this->region->evict($key);
|
||||
|
||||
$isChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isChanged) {
|
||||
$this->timestampRegion->update($this->timestampKey);
|
||||
}
|
||||
|
||||
$this->queuedCache = [];
|
||||
}
|
||||
|
||||
public function afterTransactionRolledBack(): void
|
||||
{
|
||||
$this->queuedCache = [];
|
||||
}
|
||||
|
||||
public function delete(object $entity): bool
|
||||
{
|
||||
$key = new EntityCacheKey($this->class->rootEntityName, $this->uow->getEntityIdentifier($entity));
|
||||
$deleted = $this->persister->delete($entity);
|
||||
|
||||
if ($deleted) {
|
||||
$this->region->evict($key);
|
||||
}
|
||||
|
||||
$this->queuedCache['delete'][] = $key;
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
public function update(object $entity): void
|
||||
{
|
||||
$this->persister->update($entity);
|
||||
|
||||
$this->queuedCache['update'][] = $entity;
|
||||
}
|
||||
|
||||
private function updateCache(object $entity, bool $isChanged): bool
|
||||
{
|
||||
$class = $this->metadataFactory->getMetadataFor($entity::class);
|
||||
$key = new EntityCacheKey($class->rootEntityName, $this->uow->getEntityIdentifier($entity));
|
||||
$entry = $this->hydrator->buildCacheEntry($class, $key, $entity);
|
||||
$cached = $this->region->put($key, $entry);
|
||||
$isChanged = $isChanged || $cached;
|
||||
|
||||
if ($cached) {
|
||||
$this->cacheLogger?->entityCachePut($this->regionName, $key);
|
||||
}
|
||||
|
||||
return $isChanged;
|
||||
}
|
||||
}
|
||||
19
backend/vendor/doctrine/orm/src/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php
vendored
Normal file
19
backend/vendor/doctrine/orm/src/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Entity;
|
||||
|
||||
use Doctrine\ORM\Cache\Exception\CannotUpdateReadOnlyEntity;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
|
||||
/**
|
||||
* Specific read-only region entity persister
|
||||
*/
|
||||
class ReadOnlyCachedEntityPersister extends NonStrictReadWriteCachedEntityPersister
|
||||
{
|
||||
public function update(object $entity): void
|
||||
{
|
||||
throw CannotUpdateReadOnlyEntity::fromEntity(DefaultProxyClassNameResolver::getClass($entity));
|
||||
}
|
||||
}
|
||||
105
backend/vendor/doctrine/orm/src/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php
vendored
Normal file
105
backend/vendor/doctrine/orm/src/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Persister\Entity;
|
||||
|
||||
use Doctrine\ORM\Cache\ConcurrentRegion;
|
||||
use Doctrine\ORM\Cache\EntityCacheKey;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Persisters\Entity\EntityPersister;
|
||||
|
||||
/**
|
||||
* Specific read-write entity persister
|
||||
*/
|
||||
class ReadWriteCachedEntityPersister extends AbstractEntityPersister
|
||||
{
|
||||
public function __construct(EntityPersister $persister, ConcurrentRegion $region, EntityManagerInterface $em, ClassMetadata $class)
|
||||
{
|
||||
parent::__construct($persister, $region, $em, $class);
|
||||
}
|
||||
|
||||
public function afterTransactionComplete(): void
|
||||
{
|
||||
$isChanged = true;
|
||||
|
||||
if (isset($this->queuedCache['update'])) {
|
||||
foreach ($this->queuedCache['update'] as $item) {
|
||||
$this->region->evict($item['key']);
|
||||
|
||||
$isChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->queuedCache['delete'])) {
|
||||
foreach ($this->queuedCache['delete'] as $item) {
|
||||
$this->region->evict($item['key']);
|
||||
|
||||
$isChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isChanged) {
|
||||
$this->timestampRegion->update($this->timestampKey);
|
||||
}
|
||||
|
||||
$this->queuedCache = [];
|
||||
}
|
||||
|
||||
public function afterTransactionRolledBack(): void
|
||||
{
|
||||
if (isset($this->queuedCache['update'])) {
|
||||
foreach ($this->queuedCache['update'] as $item) {
|
||||
$this->region->evict($item['key']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->queuedCache['delete'])) {
|
||||
foreach ($this->queuedCache['delete'] as $item) {
|
||||
$this->region->evict($item['key']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->queuedCache = [];
|
||||
}
|
||||
|
||||
public function delete(object $entity): bool
|
||||
{
|
||||
$key = new EntityCacheKey($this->class->rootEntityName, $this->uow->getEntityIdentifier($entity));
|
||||
$lock = $this->region->lock($key);
|
||||
$deleted = $this->persister->delete($entity);
|
||||
|
||||
if ($deleted) {
|
||||
$this->region->evict($key);
|
||||
}
|
||||
|
||||
if ($lock === null) {
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
$this->queuedCache['delete'][] = [
|
||||
'lock' => $lock,
|
||||
'key' => $key,
|
||||
];
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
public function update(object $entity): void
|
||||
{
|
||||
$key = new EntityCacheKey($this->class->rootEntityName, $this->uow->getEntityIdentifier($entity));
|
||||
$lock = $this->region->lock($key);
|
||||
|
||||
$this->persister->update($entity);
|
||||
|
||||
if ($lock === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->queuedCache['update'][] = [
|
||||
'lock' => $lock,
|
||||
'key' => $key,
|
||||
];
|
||||
}
|
||||
}
|
||||
28
backend/vendor/doctrine/orm/src/Cache/QueryCache.php
vendored
Normal file
28
backend/vendor/doctrine/orm/src/Cache/QueryCache.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
|
||||
/**
|
||||
* Defines the contract for caches capable of storing query results.
|
||||
* These caches should only concern themselves with storing the matching result ids.
|
||||
*/
|
||||
interface QueryCache
|
||||
{
|
||||
public function clear(): bool;
|
||||
|
||||
/** @param mixed[] $hints */
|
||||
public function put(QueryCacheKey $key, ResultSetMapping $rsm, mixed $result, array $hints = []): bool;
|
||||
|
||||
/**
|
||||
* @param mixed[] $hints
|
||||
*
|
||||
* @return mixed[]|null
|
||||
*/
|
||||
public function get(QueryCacheKey $key, ResultSetMapping $rsm, array $hints = []): array|null;
|
||||
|
||||
public function getRegion(): Region;
|
||||
}
|
||||
29
backend/vendor/doctrine/orm/src/Cache/QueryCacheEntry.php
vendored
Normal file
29
backend/vendor/doctrine/orm/src/Cache/QueryCacheEntry.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use function microtime;
|
||||
|
||||
class QueryCacheEntry implements CacheEntry
|
||||
{
|
||||
/**
|
||||
* Time creation of this cache entry
|
||||
*/
|
||||
public readonly float $time;
|
||||
|
||||
/** @param array<string, mixed> $result List of entity identifiers */
|
||||
public function __construct(
|
||||
public readonly array $result,
|
||||
float|null $time = null,
|
||||
) {
|
||||
$this->time = $time ?: microtime(true);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $values */
|
||||
public static function __set_state(array $values): self
|
||||
{
|
||||
return new self($values['result'], $values['time']);
|
||||
}
|
||||
}
|
||||
23
backend/vendor/doctrine/orm/src/Cache/QueryCacheKey.php
vendored
Normal file
23
backend/vendor/doctrine/orm/src/Cache/QueryCacheKey.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Cache;
|
||||
|
||||
/**
|
||||
* A cache key that identifies a particular query.
|
||||
*/
|
||||
class QueryCacheKey extends CacheKey
|
||||
{
|
||||
/** @param Cache::MODE_* $cacheMode */
|
||||
public function __construct(
|
||||
string $cacheId,
|
||||
public readonly int $lifetime = 0,
|
||||
public readonly int $cacheMode = Cache::MODE_NORMAL,
|
||||
public readonly TimestampCacheKey|null $timestampKey = null,
|
||||
) {
|
||||
parent::__construct($cacheId);
|
||||
}
|
||||
}
|
||||
16
backend/vendor/doctrine/orm/src/Cache/QueryCacheValidator.php
vendored
Normal file
16
backend/vendor/doctrine/orm/src/Cache/QueryCacheValidator.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
/**
|
||||
* Cache query validator interface.
|
||||
*/
|
||||
interface QueryCacheValidator
|
||||
{
|
||||
/**
|
||||
* Checks if the query entry is valid
|
||||
*/
|
||||
public function isValid(QueryCacheKey $key, QueryCacheEntry $entry): bool;
|
||||
}
|
||||
73
backend/vendor/doctrine/orm/src/Cache/Region.php
vendored
Normal file
73
backend/vendor/doctrine/orm/src/Cache/Region.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use Doctrine\ORM\Cache\Exception\CacheException;
|
||||
|
||||
/**
|
||||
* Defines a contract for accessing a particular named region.
|
||||
*/
|
||||
interface Region
|
||||
{
|
||||
/**
|
||||
* Retrieve the name of this region.
|
||||
*/
|
||||
public function getName(): string;
|
||||
|
||||
/**
|
||||
* Determine whether this region contains data for the given key.
|
||||
*
|
||||
* @param CacheKey $key The cache key
|
||||
*/
|
||||
public function contains(CacheKey $key): bool;
|
||||
|
||||
/**
|
||||
* Get an item from the cache.
|
||||
*
|
||||
* @param CacheKey $key The key of the item to be retrieved.
|
||||
*
|
||||
* @return CacheEntry|null The cached entry or NULL
|
||||
*
|
||||
* @throws CacheException Indicates a problem accessing the item or region.
|
||||
*/
|
||||
public function get(CacheKey $key): CacheEntry|null;
|
||||
|
||||
/**
|
||||
* Get all items from the cache identified by $keys.
|
||||
* It returns NULL if some elements can not be found.
|
||||
*
|
||||
* @param CollectionCacheEntry $collection The collection of the items to be retrieved.
|
||||
*
|
||||
* @return CacheEntry[]|null The cached entries or NULL if one or more entries can not be found
|
||||
*/
|
||||
public function getMultiple(CollectionCacheEntry $collection): array|null;
|
||||
|
||||
/**
|
||||
* Put an item into the cache.
|
||||
*
|
||||
* @param CacheKey $key The key under which to cache the item.
|
||||
* @param CacheEntry $entry The entry to cache.
|
||||
* @param Lock|null $lock The lock previously obtained.
|
||||
*
|
||||
* @throws CacheException Indicates a problem accessing the region.
|
||||
*/
|
||||
public function put(CacheKey $key, CacheEntry $entry, Lock|null $lock = null): bool;
|
||||
|
||||
/**
|
||||
* Remove an item from the cache.
|
||||
*
|
||||
* @param CacheKey $key The key under which to cache the item.
|
||||
*
|
||||
* @throws CacheException Indicates a problem accessing the region.
|
||||
*/
|
||||
public function evict(CacheKey $key): bool;
|
||||
|
||||
/**
|
||||
* Remove all contents of this particular cache region.
|
||||
*
|
||||
* @throws CacheException Indicates problem accessing the region.
|
||||
*/
|
||||
public function evictAll(): bool;
|
||||
}
|
||||
113
backend/vendor/doctrine/orm/src/Cache/Region/DefaultRegion.php
vendored
Normal file
113
backend/vendor/doctrine/orm/src/Cache/Region/DefaultRegion.php
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Region;
|
||||
|
||||
use Doctrine\ORM\Cache\CacheEntry;
|
||||
use Doctrine\ORM\Cache\CacheKey;
|
||||
use Doctrine\ORM\Cache\CollectionCacheEntry;
|
||||
use Doctrine\ORM\Cache\Lock;
|
||||
use Doctrine\ORM\Cache\Region;
|
||||
use Psr\Cache\CacheItemInterface;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Traversable;
|
||||
|
||||
use function array_map;
|
||||
use function iterator_to_array;
|
||||
use function strtr;
|
||||
|
||||
/**
|
||||
* The simplest cache region compatible with all doctrine-cache drivers.
|
||||
*/
|
||||
class DefaultRegion implements Region
|
||||
{
|
||||
private const REGION_KEY_SEPARATOR = '_';
|
||||
private const REGION_PREFIX = 'DC2_REGION_';
|
||||
|
||||
public function __construct(
|
||||
private readonly string $name,
|
||||
private readonly CacheItemPoolInterface $cacheItemPool,
|
||||
private readonly int $lifetime = 0,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function contains(CacheKey $key): bool
|
||||
{
|
||||
return $this->cacheItemPool->hasItem($this->getCacheEntryKey($key));
|
||||
}
|
||||
|
||||
public function get(CacheKey $key): CacheEntry|null
|
||||
{
|
||||
$item = $this->cacheItemPool->getItem($this->getCacheEntryKey($key));
|
||||
$entry = $item->isHit() ? $item->get() : null;
|
||||
|
||||
if (! $entry instanceof CacheEntry) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
public function getMultiple(CollectionCacheEntry $collection): array|null
|
||||
{
|
||||
$keys = array_map(
|
||||
$this->getCacheEntryKey(...),
|
||||
$collection->identifiers,
|
||||
);
|
||||
/** @var iterable<string, CacheItemInterface> $items */
|
||||
$items = $this->cacheItemPool->getItems($keys);
|
||||
if ($items instanceof Traversable) {
|
||||
$items = iterator_to_array($items);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($keys as $arrayKey => $cacheKey) {
|
||||
if (! isset($items[$cacheKey]) || ! $items[$cacheKey]->isHit()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$entry = $items[$cacheKey]->get();
|
||||
if (! $entry instanceof CacheEntry) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$result[$arrayKey] = $entry;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function put(CacheKey $key, CacheEntry $entry, Lock|null $lock = null): bool
|
||||
{
|
||||
$item = $this->cacheItemPool
|
||||
->getItem($this->getCacheEntryKey($key))
|
||||
->set($entry);
|
||||
|
||||
if ($this->lifetime > 0) {
|
||||
$item->expiresAfter($this->lifetime);
|
||||
}
|
||||
|
||||
return $this->cacheItemPool->save($item);
|
||||
}
|
||||
|
||||
public function evict(CacheKey $key): bool
|
||||
{
|
||||
return $this->cacheItemPool->deleteItem($this->getCacheEntryKey($key));
|
||||
}
|
||||
|
||||
public function evictAll(): bool
|
||||
{
|
||||
return $this->cacheItemPool->clear(self::REGION_PREFIX . $this->name);
|
||||
}
|
||||
|
||||
private function getCacheEntryKey(CacheKey $key): string
|
||||
{
|
||||
return self::REGION_PREFIX . $this->name . self::REGION_KEY_SEPARATOR . strtr($key->hash, '{}()/\@:', '________');
|
||||
}
|
||||
}
|
||||
194
backend/vendor/doctrine/orm/src/Cache/Region/FileLockRegion.php
vendored
Normal file
194
backend/vendor/doctrine/orm/src/Cache/Region/FileLockRegion.php
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Region;
|
||||
|
||||
use Doctrine\ORM\Cache\CacheEntry;
|
||||
use Doctrine\ORM\Cache\CacheKey;
|
||||
use Doctrine\ORM\Cache\CollectionCacheEntry;
|
||||
use Doctrine\ORM\Cache\ConcurrentRegion;
|
||||
use Doctrine\ORM\Cache\Lock;
|
||||
use Doctrine\ORM\Cache\Region;
|
||||
use InvalidArgumentException;
|
||||
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
use function chmod;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function fileatime;
|
||||
use function glob;
|
||||
use function is_dir;
|
||||
use function is_file;
|
||||
use function is_writable;
|
||||
use function mkdir;
|
||||
use function sprintf;
|
||||
use function time;
|
||||
use function unlink;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const LOCK_EX;
|
||||
|
||||
/**
|
||||
* Very naive concurrent region, based on file locks.
|
||||
*/
|
||||
class FileLockRegion implements ConcurrentRegion
|
||||
{
|
||||
final public const LOCK_EXTENSION = 'lock';
|
||||
|
||||
/**
|
||||
* @param numeric-string|int $lockLifetime
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly Region $region,
|
||||
private readonly string $directory,
|
||||
private readonly string|int $lockLifetime,
|
||||
) {
|
||||
if (! is_dir($directory) && ! @mkdir($directory, 0775, true)) {
|
||||
throw new InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $directory));
|
||||
}
|
||||
|
||||
if (! is_writable($directory)) {
|
||||
throw new InvalidArgumentException(sprintf('The directory "%s" is not writable.', $directory));
|
||||
}
|
||||
}
|
||||
|
||||
private function isLocked(CacheKey $key, Lock|null $lock = null): bool
|
||||
{
|
||||
$filename = $this->getLockFileName($key);
|
||||
|
||||
if (! is_file($filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$time = $this->getLockTime($filename);
|
||||
$content = $this->getLockContent($filename);
|
||||
|
||||
if ($content === false || $time === false) {
|
||||
@unlink($filename);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($lock && $content === $lock->value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// outdated lock
|
||||
if ($time + $this->lockLifetime <= time()) {
|
||||
@unlink($filename);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getLockFileName(CacheKey $key): string
|
||||
{
|
||||
return $this->directory . DIRECTORY_SEPARATOR . $key->hash . '.' . self::LOCK_EXTENSION;
|
||||
}
|
||||
|
||||
private function getLockContent(string $filename): string|false
|
||||
{
|
||||
return @file_get_contents($filename);
|
||||
}
|
||||
|
||||
private function getLockTime(string $filename): int|false
|
||||
{
|
||||
return @fileatime($filename);
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->region->getName();
|
||||
}
|
||||
|
||||
public function contains(CacheKey $key): bool
|
||||
{
|
||||
if ($this->isLocked($key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->region->contains($key);
|
||||
}
|
||||
|
||||
public function get(CacheKey $key): CacheEntry|null
|
||||
{
|
||||
if ($this->isLocked($key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->region->get($key);
|
||||
}
|
||||
|
||||
public function getMultiple(CollectionCacheEntry $collection): array|null
|
||||
{
|
||||
if (array_filter(array_map($this->isLocked(...), $collection->identifiers))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->region->getMultiple($collection);
|
||||
}
|
||||
|
||||
public function put(CacheKey $key, CacheEntry $entry, Lock|null $lock = null): bool
|
||||
{
|
||||
if ($this->isLocked($key, $lock)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->region->put($key, $entry);
|
||||
}
|
||||
|
||||
public function evict(CacheKey $key): bool
|
||||
{
|
||||
if ($this->isLocked($key)) {
|
||||
@unlink($this->getLockFileName($key));
|
||||
}
|
||||
|
||||
return $this->region->evict($key);
|
||||
}
|
||||
|
||||
public function evictAll(): bool
|
||||
{
|
||||
// The check below is necessary because on some platforms glob returns false
|
||||
// when nothing matched (even though no errors occurred)
|
||||
$filenames = glob(sprintf('%s/*.%s', $this->directory, self::LOCK_EXTENSION)) ?: [];
|
||||
|
||||
foreach ($filenames as $filename) {
|
||||
@unlink($filename);
|
||||
}
|
||||
|
||||
return $this->region->evictAll();
|
||||
}
|
||||
|
||||
public function lock(CacheKey $key): Lock|null
|
||||
{
|
||||
if ($this->isLocked($key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$lock = Lock::createLockRead();
|
||||
$filename = $this->getLockFileName($key);
|
||||
|
||||
if (@file_put_contents($filename, $lock->value, LOCK_EX) === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
chmod($filename, 0664);
|
||||
|
||||
return $lock;
|
||||
}
|
||||
|
||||
public function unlock(CacheKey $key, Lock $lock): bool
|
||||
{
|
||||
if ($this->isLocked($key, $lock)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return @unlink($this->getLockFileName($key));
|
||||
}
|
||||
}
|
||||
20
backend/vendor/doctrine/orm/src/Cache/Region/UpdateTimestampCache.php
vendored
Normal file
20
backend/vendor/doctrine/orm/src/Cache/Region/UpdateTimestampCache.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache\Region;
|
||||
|
||||
use Doctrine\ORM\Cache\CacheKey;
|
||||
use Doctrine\ORM\Cache\TimestampCacheEntry;
|
||||
use Doctrine\ORM\Cache\TimestampRegion;
|
||||
|
||||
/**
|
||||
* Tracks the timestamps of the most recent updates to particular keys.
|
||||
*/
|
||||
class UpdateTimestampCache extends DefaultRegion implements TimestampRegion
|
||||
{
|
||||
public function update(CacheKey $key): void
|
||||
{
|
||||
$this->put($key, new TimestampCacheEntry());
|
||||
}
|
||||
}
|
||||
63
backend/vendor/doctrine/orm/src/Cache/RegionsConfiguration.php
vendored
Normal file
63
backend/vendor/doctrine/orm/src/Cache/RegionsConfiguration.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
/**
|
||||
* Cache regions configuration
|
||||
*/
|
||||
class RegionsConfiguration
|
||||
{
|
||||
/** @var array<string,int> */
|
||||
private array $lifetimes = [];
|
||||
|
||||
/** @var array<string,int> */
|
||||
private array $lockLifetimes = [];
|
||||
|
||||
public function __construct(
|
||||
private int $defaultLifetime = 3600,
|
||||
private int $defaultLockLifetime = 60,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getDefaultLifetime(): int
|
||||
{
|
||||
return $this->defaultLifetime;
|
||||
}
|
||||
|
||||
public function setDefaultLifetime(int $defaultLifetime): void
|
||||
{
|
||||
$this->defaultLifetime = $defaultLifetime;
|
||||
}
|
||||
|
||||
public function getDefaultLockLifetime(): int
|
||||
{
|
||||
return $this->defaultLockLifetime;
|
||||
}
|
||||
|
||||
public function setDefaultLockLifetime(int $defaultLockLifetime): void
|
||||
{
|
||||
$this->defaultLockLifetime = $defaultLockLifetime;
|
||||
}
|
||||
|
||||
public function getLifetime(string $regionName): int
|
||||
{
|
||||
return $this->lifetimes[$regionName] ?? $this->defaultLifetime;
|
||||
}
|
||||
|
||||
public function setLifetime(string $name, int $lifetime): void
|
||||
{
|
||||
$this->lifetimes[$name] = $lifetime;
|
||||
}
|
||||
|
||||
public function getLockLifetime(string $regionName): int
|
||||
{
|
||||
return $this->lockLifetimes[$regionName] ?? $this->defaultLockLifetime;
|
||||
}
|
||||
|
||||
public function setLockLifetime(string $name, int $lifetime): void
|
||||
{
|
||||
$this->lockLifetimes[$name] = $lifetime;
|
||||
}
|
||||
}
|
||||
29
backend/vendor/doctrine/orm/src/Cache/TimestampCacheEntry.php
vendored
Normal file
29
backend/vendor/doctrine/orm/src/Cache/TimestampCacheEntry.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use function microtime;
|
||||
|
||||
class TimestampCacheEntry implements CacheEntry
|
||||
{
|
||||
public readonly float $time;
|
||||
|
||||
public function __construct(float|null $time = null)
|
||||
{
|
||||
$this->time = $time ?? microtime(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TimestampCacheEntry
|
||||
*
|
||||
* This method allow Doctrine\Common\Cache\PhpFileCache compatibility
|
||||
*
|
||||
* @param array<string,float> $values array containing property values
|
||||
*/
|
||||
public static function __set_state(array $values): TimestampCacheEntry
|
||||
{
|
||||
return new self($values['time']);
|
||||
}
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Cache/TimestampCacheKey.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Cache/TimestampCacheKey.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
/**
|
||||
* A key that identifies a timestamped space.
|
||||
*/
|
||||
class TimestampCacheKey extends CacheKey
|
||||
{
|
||||
/** @param string $space Result cache id */
|
||||
public function __construct(string $space)
|
||||
{
|
||||
parent::__construct($space);
|
||||
}
|
||||
}
|
||||
38
backend/vendor/doctrine/orm/src/Cache/TimestampQueryCacheValidator.php
vendored
Normal file
38
backend/vendor/doctrine/orm/src/Cache/TimestampQueryCacheValidator.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
use function microtime;
|
||||
|
||||
class TimestampQueryCacheValidator implements QueryCacheValidator
|
||||
{
|
||||
public function __construct(private readonly TimestampRegion $timestampRegion)
|
||||
{
|
||||
}
|
||||
|
||||
public function isValid(QueryCacheKey $key, QueryCacheEntry $entry): bool
|
||||
{
|
||||
if ($this->regionUpdated($key, $entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($key->lifetime === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $entry->time + $key->lifetime > microtime(true);
|
||||
}
|
||||
|
||||
private function regionUpdated(QueryCacheKey $key, QueryCacheEntry $entry): bool
|
||||
{
|
||||
if ($key->timestampKey === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$timestamp = $this->timestampRegion->get($key->timestampKey);
|
||||
|
||||
return $timestamp && $timestamp->time > $entry->time;
|
||||
}
|
||||
}
|
||||
18
backend/vendor/doctrine/orm/src/Cache/TimestampRegion.php
vendored
Normal file
18
backend/vendor/doctrine/orm/src/Cache/TimestampRegion.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Cache;
|
||||
|
||||
/**
|
||||
* Defines the contract for a cache region which will specifically be used to store entity "update timestamps".
|
||||
*/
|
||||
interface TimestampRegion extends Region
|
||||
{
|
||||
/**
|
||||
* Update a specific key into the cache region.
|
||||
*
|
||||
* @throws LockException Indicates a problem accessing the region.
|
||||
*/
|
||||
public function update(CacheKey $key): void;
|
||||
}
|
||||
726
backend/vendor/doctrine/orm/src/Configuration.php
vendored
Normal file
726
backend/vendor/doctrine/orm/src/Configuration.php
vendored
Normal file
@@ -0,0 +1,726 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use Doctrine\ORM\Cache\CacheConfiguration;
|
||||
use Doctrine\ORM\Exception\InvalidEntityRepository;
|
||||
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\ORM\Mapping\DefaultEntityListenerResolver;
|
||||
use Doctrine\ORM\Mapping\DefaultNamingStrategy;
|
||||
use Doctrine\ORM\Mapping\DefaultQuoteStrategy;
|
||||
use Doctrine\ORM\Mapping\EntityListenerResolver;
|
||||
use Doctrine\ORM\Mapping\NamingStrategy;
|
||||
use Doctrine\ORM\Mapping\QuoteStrategy;
|
||||
use Doctrine\ORM\Mapping\TypedFieldMapper;
|
||||
use Doctrine\ORM\Proxy\ProxyFactory;
|
||||
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
|
||||
use Doctrine\ORM\Query\Filter\SQLFilter;
|
||||
use Doctrine\ORM\Repository\DefaultRepositoryFactory;
|
||||
use Doctrine\ORM\Repository\RepositoryFactory;
|
||||
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
|
||||
use LogicException;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
|
||||
use function class_exists;
|
||||
use function is_a;
|
||||
use function strtolower;
|
||||
|
||||
use const PHP_VERSION_ID;
|
||||
|
||||
/**
|
||||
* Configuration container for all configuration options of Doctrine.
|
||||
* It combines all configuration options from DBAL & ORM.
|
||||
*
|
||||
* Internal note: When adding a new configuration option just write a getter/setter pair.
|
||||
*/
|
||||
class Configuration extends \Doctrine\DBAL\Configuration
|
||||
{
|
||||
/** @var mixed[] */
|
||||
protected array $attributes = [];
|
||||
|
||||
/** @phpstan-var array<class-string<AbstractPlatform>, ClassMetadata::GENERATOR_TYPE_*> */
|
||||
private $identityGenerationPreferences = [];
|
||||
|
||||
/** @phpstan-param array<class-string<AbstractPlatform>, ClassMetadata::GENERATOR_TYPE_*> $value */
|
||||
public function setIdentityGenerationPreferences(array $value): void
|
||||
{
|
||||
$this->identityGenerationPreferences = $value;
|
||||
}
|
||||
|
||||
/** @phpstan-return array<class-string<AbstractPlatform>, ClassMetadata::GENERATOR_TYPE_*> $value */
|
||||
public function getIdentityGenerationPreferences(): array
|
||||
{
|
||||
return $this->identityGenerationPreferences;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the directory where Doctrine generates any necessary proxy class files.
|
||||
*/
|
||||
public function setProxyDir(string $dir): void
|
||||
{
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
Deprecation::triggerIfCalledFromOutside(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/12005',
|
||||
'Calling %s is deprecated and will not be possible in Doctrine ORM 4.0.',
|
||||
__METHOD__,
|
||||
);
|
||||
}
|
||||
|
||||
$this->attributes['proxyDir'] = $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the directory where Doctrine generates any necessary proxy class files.
|
||||
*/
|
||||
public function getProxyDir(): string|null
|
||||
{
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/12005',
|
||||
'Calling %s is deprecated and will not be possible in Doctrine ORM 4.0.',
|
||||
__METHOD__,
|
||||
);
|
||||
}
|
||||
|
||||
return $this->attributes['proxyDir'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the strategy for automatically generating proxy classes.
|
||||
*
|
||||
* @return ProxyFactory::AUTOGENERATE_*
|
||||
*/
|
||||
public function getAutoGenerateProxyClasses(): int
|
||||
{
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/12005',
|
||||
'Calling %s is deprecated and will not be possible in Doctrine ORM 4.0.',
|
||||
__METHOD__,
|
||||
);
|
||||
}
|
||||
|
||||
return $this->attributes['autoGenerateProxyClasses'] ?? ProxyFactory::AUTOGENERATE_ALWAYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy for automatically generating proxy classes.
|
||||
*
|
||||
* @param bool|ProxyFactory::AUTOGENERATE_* $autoGenerate True is converted to AUTOGENERATE_ALWAYS, false to AUTOGENERATE_NEVER.
|
||||
*/
|
||||
public function setAutoGenerateProxyClasses(bool|int $autoGenerate): void
|
||||
{
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
Deprecation::triggerIfCalledFromOutside(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/12005',
|
||||
'Calling %s is deprecated and will not be possible in Doctrine ORM 4.0.',
|
||||
__METHOD__,
|
||||
);
|
||||
}
|
||||
|
||||
$this->attributes['autoGenerateProxyClasses'] = (int) $autoGenerate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the namespace where proxy classes reside.
|
||||
*/
|
||||
public function getProxyNamespace(): string|null
|
||||
{
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/12005',
|
||||
'Calling %s is deprecated and will not be possible in Doctrine ORM 4.0.',
|
||||
__METHOD__,
|
||||
);
|
||||
}
|
||||
|
||||
return $this->attributes['proxyNamespace'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the namespace where proxy classes reside.
|
||||
*/
|
||||
public function setProxyNamespace(string $ns): void
|
||||
{
|
||||
if (PHP_VERSION_ID >= 80400) {
|
||||
Deprecation::triggerIfCalledFromOutside(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/12005',
|
||||
'Calling %s is deprecated and will not be possible in Doctrine ORM 4.0.',
|
||||
__METHOD__,
|
||||
);
|
||||
}
|
||||
|
||||
$this->attributes['proxyNamespace'] = $ns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache driver implementation that is used for metadata caching.
|
||||
*
|
||||
* @todo Force parameter to be a Closure to ensure lazy evaluation
|
||||
* (as soon as a metadata cache is in effect, the driver never needs to initialize).
|
||||
*/
|
||||
public function setMetadataDriverImpl(MappingDriver $driverImpl): void
|
||||
{
|
||||
$this->attributes['metadataDriverImpl'] = $driverImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entity alias map.
|
||||
*
|
||||
* @phpstan-param array<string, string> $entityNamespaces
|
||||
*/
|
||||
public function setEntityNamespaces(array $entityNamespaces): void
|
||||
{
|
||||
$this->attributes['entityNamespaces'] = $entityNamespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of registered entity namespace aliases.
|
||||
*
|
||||
* @phpstan-return array<string, string>
|
||||
*/
|
||||
public function getEntityNamespaces(): array
|
||||
{
|
||||
return $this->attributes['entityNamespaces'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache driver implementation that is used for the mapping metadata.
|
||||
*/
|
||||
public function getMetadataDriverImpl(): MappingDriver|null
|
||||
{
|
||||
return $this->attributes['metadataDriverImpl'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache driver implementation that is used for the query cache (SQL cache).
|
||||
*/
|
||||
public function getQueryCache(): CacheItemPoolInterface|null
|
||||
{
|
||||
return $this->attributes['queryCache'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache driver implementation that is used for the query cache (SQL cache).
|
||||
*/
|
||||
public function setQueryCache(CacheItemPoolInterface $cache): void
|
||||
{
|
||||
$this->attributes['queryCache'] = $cache;
|
||||
}
|
||||
|
||||
public function getHydrationCache(): CacheItemPoolInterface|null
|
||||
{
|
||||
return $this->attributes['hydrationCache'] ?? null;
|
||||
}
|
||||
|
||||
public function setHydrationCache(CacheItemPoolInterface $cache): void
|
||||
{
|
||||
$this->attributes['hydrationCache'] = $cache;
|
||||
}
|
||||
|
||||
public function getMetadataCache(): CacheItemPoolInterface|null
|
||||
{
|
||||
return $this->attributes['metadataCache'] ?? null;
|
||||
}
|
||||
|
||||
public function setMetadataCache(CacheItemPoolInterface $cache): void
|
||||
{
|
||||
$this->attributes['metadataCache'] = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom DQL function that produces a string value.
|
||||
* Such a function can then be used in any DQL statement in any place where string
|
||||
* functions are allowed.
|
||||
*
|
||||
* DQL function names are case-insensitive.
|
||||
*
|
||||
* @param class-string|callable $className Class name or a callable that returns the function.
|
||||
* @phpstan-param class-string<FunctionNode>|callable(string):FunctionNode $className
|
||||
*/
|
||||
public function addCustomStringFunction(string $name, string|callable $className): void
|
||||
{
|
||||
$this->attributes['customStringFunctions'][strtolower($name)] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the implementation class name of a registered custom string DQL function.
|
||||
*
|
||||
* @phpstan-return class-string<FunctionNode>|callable(string):FunctionNode|null
|
||||
*/
|
||||
public function getCustomStringFunction(string $name): string|callable|null
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
return $this->attributes['customStringFunctions'][$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a map of custom DQL string functions.
|
||||
*
|
||||
* Keys must be function names and values the FQCN of the implementing class.
|
||||
* The function names will be case-insensitive in DQL.
|
||||
*
|
||||
* Any previously added string functions are discarded.
|
||||
*
|
||||
* @phpstan-param array<string, class-string<FunctionNode>|callable(string):FunctionNode> $functions The map of custom
|
||||
* DQL string functions.
|
||||
*/
|
||||
public function setCustomStringFunctions(array $functions): void
|
||||
{
|
||||
foreach ($functions as $name => $className) {
|
||||
$this->addCustomStringFunction($name, $className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom DQL function that produces a numeric value.
|
||||
* Such a function can then be used in any DQL statement in any place where numeric
|
||||
* functions are allowed.
|
||||
*
|
||||
* DQL function names are case-insensitive.
|
||||
*
|
||||
* @param class-string|callable $className Class name or a callable that returns the function.
|
||||
* @phpstan-param class-string<FunctionNode>|callable(string):FunctionNode $className
|
||||
*/
|
||||
public function addCustomNumericFunction(string $name, string|callable $className): void
|
||||
{
|
||||
$this->attributes['customNumericFunctions'][strtolower($name)] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the implementation class name of a registered custom numeric DQL function.
|
||||
*
|
||||
* @phpstan-return class-string<FunctionNode>|callable(string):FunctionNode|null
|
||||
*/
|
||||
public function getCustomNumericFunction(string $name): string|callable|null
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
return $this->attributes['customNumericFunctions'][$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a map of custom DQL numeric functions.
|
||||
*
|
||||
* Keys must be function names and values the FQCN of the implementing class.
|
||||
* The function names will be case-insensitive in DQL.
|
||||
*
|
||||
* Any previously added numeric functions are discarded.
|
||||
*
|
||||
* @param array<string, class-string> $functions The map of custom
|
||||
* DQL numeric functions.
|
||||
*/
|
||||
public function setCustomNumericFunctions(array $functions): void
|
||||
{
|
||||
foreach ($functions as $name => $className) {
|
||||
$this->addCustomNumericFunction($name, $className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom DQL function that produces a date/time value.
|
||||
* Such a function can then be used in any DQL statement in any place where date/time
|
||||
* functions are allowed.
|
||||
*
|
||||
* DQL function names are case-insensitive.
|
||||
*
|
||||
* @param string|callable $className Class name or a callable that returns the function.
|
||||
* @phpstan-param class-string<FunctionNode>|callable(string):FunctionNode $className
|
||||
*/
|
||||
public function addCustomDatetimeFunction(string $name, string|callable $className): void
|
||||
{
|
||||
$this->attributes['customDatetimeFunctions'][strtolower($name)] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the implementation class name of a registered custom date/time DQL function.
|
||||
*
|
||||
* @return class-string|callable|null
|
||||
*/
|
||||
public function getCustomDatetimeFunction(string $name): string|callable|null
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
return $this->attributes['customDatetimeFunctions'][$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a map of custom DQL date/time functions.
|
||||
*
|
||||
* Keys must be function names and values the FQCN of the implementing class.
|
||||
* The function names will be case-insensitive in DQL.
|
||||
*
|
||||
* Any previously added date/time functions are discarded.
|
||||
*
|
||||
* @param array $functions The map of custom DQL date/time functions.
|
||||
* @phpstan-param array<string, class-string<FunctionNode>|callable(string):FunctionNode> $functions
|
||||
*/
|
||||
public function setCustomDatetimeFunctions(array $functions): void
|
||||
{
|
||||
foreach ($functions as $name => $className) {
|
||||
$this->addCustomDatetimeFunction($name, $className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a TypedFieldMapper for php typed fields to DBAL types auto-completion.
|
||||
*/
|
||||
public function setTypedFieldMapper(TypedFieldMapper|null $typedFieldMapper): void
|
||||
{
|
||||
$this->attributes['typedFieldMapper'] = $typedFieldMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a TypedFieldMapper for php typed fields to DBAL types auto-completion.
|
||||
*/
|
||||
public function getTypedFieldMapper(): TypedFieldMapper|null
|
||||
{
|
||||
return $this->attributes['typedFieldMapper'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the custom hydrator modes in one pass.
|
||||
*
|
||||
* @param array<string, class-string<AbstractHydrator>> $modes An array of ($modeName => $hydrator).
|
||||
*/
|
||||
public function setCustomHydrationModes(array $modes): void
|
||||
{
|
||||
$this->attributes['customHydrationModes'] = [];
|
||||
|
||||
foreach ($modes as $modeName => $hydrator) {
|
||||
$this->addCustomHydrationMode($modeName, $hydrator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hydrator class for the given hydration mode name.
|
||||
*
|
||||
* @return class-string<AbstractHydrator>|null
|
||||
*/
|
||||
public function getCustomHydrationMode(string $modeName): string|null
|
||||
{
|
||||
return $this->attributes['customHydrationModes'][$modeName] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom hydration mode.
|
||||
*
|
||||
* @param class-string<AbstractHydrator> $hydrator
|
||||
*/
|
||||
public function addCustomHydrationMode(string $modeName, string $hydrator): void
|
||||
{
|
||||
$this->attributes['customHydrationModes'][$modeName] = $hydrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a class metadata factory.
|
||||
*
|
||||
* @param class-string $cmfName
|
||||
*/
|
||||
public function setClassMetadataFactoryName(string $cmfName): void
|
||||
{
|
||||
$this->attributes['classMetadataFactoryName'] = $cmfName;
|
||||
}
|
||||
|
||||
/** @return class-string */
|
||||
public function getClassMetadataFactoryName(): string
|
||||
{
|
||||
if (! isset($this->attributes['classMetadataFactoryName'])) {
|
||||
$this->attributes['classMetadataFactoryName'] = ClassMetadataFactory::class;
|
||||
}
|
||||
|
||||
return $this->attributes['classMetadataFactoryName'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filter to the list of possible filters.
|
||||
*
|
||||
* @param class-string<SQLFilter> $className The class name of the filter.
|
||||
*/
|
||||
public function addFilter(string $name, string $className): void
|
||||
{
|
||||
$this->attributes['filters'][$name] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class name for a given filter name.
|
||||
*
|
||||
* @return class-string<SQLFilter>|null The class name of the filter,
|
||||
* or null if it is not defined.
|
||||
*/
|
||||
public function getFilterClassName(string $name): string|null
|
||||
{
|
||||
return $this->attributes['filters'][$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default repository class.
|
||||
*
|
||||
* @param class-string<EntityRepository> $className
|
||||
*
|
||||
* @throws InvalidEntityRepository If $classname is not an ObjectRepository.
|
||||
*/
|
||||
public function setDefaultRepositoryClassName(string $className): void
|
||||
{
|
||||
if (! class_exists($className) || ! is_a($className, EntityRepository::class, true)) {
|
||||
throw InvalidEntityRepository::fromClassName($className);
|
||||
}
|
||||
|
||||
$this->attributes['defaultRepositoryClassName'] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default repository class.
|
||||
*
|
||||
* @return class-string<EntityRepository>
|
||||
*/
|
||||
public function getDefaultRepositoryClassName(): string
|
||||
{
|
||||
return $this->attributes['defaultRepositoryClassName'] ?? EntityRepository::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets naming strategy.
|
||||
*/
|
||||
public function setNamingStrategy(NamingStrategy $namingStrategy): void
|
||||
{
|
||||
$this->attributes['namingStrategy'] = $namingStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets naming strategy..
|
||||
*/
|
||||
public function getNamingStrategy(): NamingStrategy
|
||||
{
|
||||
if (! isset($this->attributes['namingStrategy'])) {
|
||||
$this->attributes['namingStrategy'] = new DefaultNamingStrategy();
|
||||
}
|
||||
|
||||
return $this->attributes['namingStrategy'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets quote strategy.
|
||||
*/
|
||||
public function setQuoteStrategy(QuoteStrategy $quoteStrategy): void
|
||||
{
|
||||
$this->attributes['quoteStrategy'] = $quoteStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets quote strategy.
|
||||
*/
|
||||
public function getQuoteStrategy(): QuoteStrategy
|
||||
{
|
||||
if (! isset($this->attributes['quoteStrategy'])) {
|
||||
$this->attributes['quoteStrategy'] = new DefaultQuoteStrategy();
|
||||
}
|
||||
|
||||
return $this->attributes['quoteStrategy'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the entity listener resolver.
|
||||
*/
|
||||
public function setEntityListenerResolver(EntityListenerResolver $resolver): void
|
||||
{
|
||||
$this->attributes['entityListenerResolver'] = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity listener resolver.
|
||||
*/
|
||||
public function getEntityListenerResolver(): EntityListenerResolver
|
||||
{
|
||||
if (! isset($this->attributes['entityListenerResolver'])) {
|
||||
$this->attributes['entityListenerResolver'] = new DefaultEntityListenerResolver();
|
||||
}
|
||||
|
||||
return $this->attributes['entityListenerResolver'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the entity repository factory.
|
||||
*/
|
||||
public function setRepositoryFactory(RepositoryFactory $repositoryFactory): void
|
||||
{
|
||||
$this->attributes['repositoryFactory'] = $repositoryFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity repository factory.
|
||||
*/
|
||||
public function getRepositoryFactory(): RepositoryFactory
|
||||
{
|
||||
return $this->attributes['repositoryFactory'] ?? new DefaultRepositoryFactory();
|
||||
}
|
||||
|
||||
public function isSecondLevelCacheEnabled(): bool
|
||||
{
|
||||
return $this->attributes['isSecondLevelCacheEnabled'] ?? false;
|
||||
}
|
||||
|
||||
public function setSecondLevelCacheEnabled(bool $flag = true): void
|
||||
{
|
||||
$this->attributes['isSecondLevelCacheEnabled'] = $flag;
|
||||
}
|
||||
|
||||
public function setSecondLevelCacheConfiguration(CacheConfiguration $cacheConfig): void
|
||||
{
|
||||
$this->attributes['secondLevelCacheConfiguration'] = $cacheConfig;
|
||||
}
|
||||
|
||||
public function getSecondLevelCacheConfiguration(): CacheConfiguration|null
|
||||
{
|
||||
if (! isset($this->attributes['secondLevelCacheConfiguration']) && $this->isSecondLevelCacheEnabled()) {
|
||||
$this->attributes['secondLevelCacheConfiguration'] = new CacheConfiguration();
|
||||
}
|
||||
|
||||
return $this->attributes['secondLevelCacheConfiguration'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns query hints, which will be applied to every query in application
|
||||
*
|
||||
* @phpstan-return array<string, mixed>
|
||||
*/
|
||||
public function getDefaultQueryHints(): array
|
||||
{
|
||||
return $this->attributes['defaultQueryHints'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets array of query hints, which will be applied to every query in application
|
||||
*
|
||||
* @phpstan-param array<string, mixed> $defaultQueryHints
|
||||
*/
|
||||
public function setDefaultQueryHints(array $defaultQueryHints): void
|
||||
{
|
||||
$this->attributes['defaultQueryHints'] = $defaultQueryHints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a default query hint. If the hint name is not recognized, FALSE is returned.
|
||||
*
|
||||
* @return mixed The value of the hint or FALSE, if the hint name is not recognized.
|
||||
*/
|
||||
public function getDefaultQueryHint(string $name): mixed
|
||||
{
|
||||
return $this->attributes['defaultQueryHints'][$name] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a default query hint. If the hint name is not recognized, it is silently ignored.
|
||||
*/
|
||||
public function setDefaultQueryHint(string $name, mixed $value): void
|
||||
{
|
||||
$this->attributes['defaultQueryHints'][$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of entity class names to be ignored by the SchemaTool
|
||||
*
|
||||
* @return list<class-string>
|
||||
*/
|
||||
public function getSchemaIgnoreClasses(): array
|
||||
{
|
||||
return $this->attributes['schemaIgnoreClasses'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of entity class names to be ignored by the SchemaTool
|
||||
*
|
||||
* @param list<class-string> $schemaIgnoreClasses List of entity class names
|
||||
*/
|
||||
public function setSchemaIgnoreClasses(array $schemaIgnoreClasses): void
|
||||
{
|
||||
$this->attributes['schemaIgnoreClasses'] = $schemaIgnoreClasses;
|
||||
}
|
||||
|
||||
public function isNativeLazyObjectsEnabled(): bool
|
||||
{
|
||||
return $this->attributes['nativeLazyObjects'] ?? false;
|
||||
}
|
||||
|
||||
public function enableNativeLazyObjects(bool $nativeLazyObjects): void
|
||||
{
|
||||
if (PHP_VERSION_ID >= 80400 && ! $nativeLazyObjects) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/12005',
|
||||
'Disabling native lazy objects is deprecated and will be impossible in Doctrine ORM 4.0.',
|
||||
);
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID < 80400 && $nativeLazyObjects) {
|
||||
throw new LogicException('Lazy loading proxies require PHP 8.4 or higher.');
|
||||
}
|
||||
|
||||
$this->attributes['nativeLazyObjects'] = $nativeLazyObjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated lazy ghost objects are always enabled
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function isLazyGhostObjectEnabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @deprecated lazy ghost objects cannot be disabled */
|
||||
public function setLazyGhostObjectEnabled(bool $flag): void
|
||||
{
|
||||
if (! $flag) {
|
||||
throw new LogicException(<<<'EXCEPTION'
|
||||
The lazy ghost object feature cannot be disabled anymore.
|
||||
Please remove the call to setLazyGhostObjectEnabled(false).
|
||||
EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated rejecting ID collisions in the identity map cannot be disabled */
|
||||
public function setRejectIdCollisionInIdentityMap(bool $flag): void
|
||||
{
|
||||
if (! $flag) {
|
||||
throw new LogicException(<<<'EXCEPTION'
|
||||
Rejecting ID collisions in the identity map cannot be disabled anymore.
|
||||
Please remove the call to setRejectIdCollisionInIdentityMap(false).
|
||||
EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated rejecting ID collisions in the identity map is always enabled
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function isRejectIdCollisionInIdentityMapEnabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setEagerFetchBatchSize(int $batchSize = 100): void
|
||||
{
|
||||
$this->attributes['fetchModeSubselectBatchSize'] = $batchSize;
|
||||
}
|
||||
|
||||
public function getEagerFetchBatchSize(): int
|
||||
{
|
||||
return $this->attributes['fetchModeSubselectBatchSize'] ?? 100;
|
||||
}
|
||||
}
|
||||
174
backend/vendor/doctrine/orm/src/Decorator/EntityManagerDecorator.php
vendored
Normal file
174
backend/vendor/doctrine/orm/src/Decorator/EntityManagerDecorator.php
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Decorator;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Doctrine\Common\EventManager;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\LockMode;
|
||||
use Doctrine\ORM\Cache;
|
||||
use Doctrine\ORM\Configuration;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\ORM\NativeQuery;
|
||||
use Doctrine\ORM\Proxy\ProxyFactory;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\Query\FilterCollection;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
use Doctrine\Persistence\ObjectManagerDecorator;
|
||||
|
||||
/**
|
||||
* Base class for EntityManager decorators
|
||||
*
|
||||
* @extends ObjectManagerDecorator<EntityManagerInterface>
|
||||
*/
|
||||
abstract class EntityManagerDecorator extends ObjectManagerDecorator implements EntityManagerInterface
|
||||
{
|
||||
public function __construct(EntityManagerInterface $wrapped)
|
||||
{
|
||||
$this->wrapped = $wrapped;
|
||||
}
|
||||
|
||||
public function getRepository(string $className): EntityRepository
|
||||
{
|
||||
return $this->wrapped->getRepository($className);
|
||||
}
|
||||
|
||||
public function getMetadataFactory(): ClassMetadataFactory
|
||||
{
|
||||
return $this->wrapped->getMetadataFactory();
|
||||
}
|
||||
|
||||
public function getClassMetadata(string $className): ClassMetadata
|
||||
{
|
||||
return $this->wrapped->getClassMetadata($className);
|
||||
}
|
||||
|
||||
public function getConnection(): Connection
|
||||
{
|
||||
return $this->wrapped->getConnection();
|
||||
}
|
||||
|
||||
public function getExpressionBuilder(): Expr
|
||||
{
|
||||
return $this->wrapped->getExpressionBuilder();
|
||||
}
|
||||
|
||||
public function beginTransaction(): void
|
||||
{
|
||||
$this->wrapped->beginTransaction();
|
||||
}
|
||||
|
||||
public function wrapInTransaction(callable $func): mixed
|
||||
{
|
||||
return $this->wrapped->wrapInTransaction($func);
|
||||
}
|
||||
|
||||
public function commit(): void
|
||||
{
|
||||
$this->wrapped->commit();
|
||||
}
|
||||
|
||||
public function rollback(): void
|
||||
{
|
||||
$this->wrapped->rollback();
|
||||
}
|
||||
|
||||
public function createQuery(string $dql = ''): Query
|
||||
{
|
||||
return $this->wrapped->createQuery($dql);
|
||||
}
|
||||
|
||||
public function createNativeQuery(string $sql, ResultSetMapping $rsm): NativeQuery
|
||||
{
|
||||
return $this->wrapped->createNativeQuery($sql, $rsm);
|
||||
}
|
||||
|
||||
public function createQueryBuilder(): QueryBuilder
|
||||
{
|
||||
return $this->wrapped->createQueryBuilder();
|
||||
}
|
||||
|
||||
public function getReference(string $entityName, mixed $id): object|null
|
||||
{
|
||||
return $this->wrapped->getReference($entityName, $id);
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
$this->wrapped->close();
|
||||
}
|
||||
|
||||
public function lock(object $entity, LockMode|int $lockMode, DateTimeInterface|int|null $lockVersion = null): void
|
||||
{
|
||||
$this->wrapped->lock($entity, $lockMode, $lockVersion);
|
||||
}
|
||||
|
||||
public function find(string $className, mixed $id, LockMode|int|null $lockMode = null, int|null $lockVersion = null): object|null
|
||||
{
|
||||
return $this->wrapped->find($className, $id, $lockMode, $lockVersion);
|
||||
}
|
||||
|
||||
public function refresh(object $object, LockMode|int|null $lockMode = null): void
|
||||
{
|
||||
$this->wrapped->refresh($object, $lockMode);
|
||||
}
|
||||
|
||||
public function getEventManager(): EventManager
|
||||
{
|
||||
return $this->wrapped->getEventManager();
|
||||
}
|
||||
|
||||
public function getConfiguration(): Configuration
|
||||
{
|
||||
return $this->wrapped->getConfiguration();
|
||||
}
|
||||
|
||||
public function isOpen(): bool
|
||||
{
|
||||
return $this->wrapped->isOpen();
|
||||
}
|
||||
|
||||
public function getUnitOfWork(): UnitOfWork
|
||||
{
|
||||
return $this->wrapped->getUnitOfWork();
|
||||
}
|
||||
|
||||
public function newHydrator(string|int $hydrationMode): AbstractHydrator
|
||||
{
|
||||
return $this->wrapped->newHydrator($hydrationMode);
|
||||
}
|
||||
|
||||
public function getProxyFactory(): ProxyFactory
|
||||
{
|
||||
return $this->wrapped->getProxyFactory();
|
||||
}
|
||||
|
||||
public function getFilters(): FilterCollection
|
||||
{
|
||||
return $this->wrapped->getFilters();
|
||||
}
|
||||
|
||||
public function isFiltersStateClean(): bool
|
||||
{
|
||||
return $this->wrapped->isFiltersStateClean();
|
||||
}
|
||||
|
||||
public function hasFilters(): bool
|
||||
{
|
||||
return $this->wrapped->hasFilters();
|
||||
}
|
||||
|
||||
public function getCache(): Cache|null
|
||||
{
|
||||
return $this->wrapped->getCache();
|
||||
}
|
||||
}
|
||||
635
backend/vendor/doctrine/orm/src/EntityManager.php
vendored
Normal file
635
backend/vendor/doctrine/orm/src/EntityManager.php
vendored
Normal file
@@ -0,0 +1,635 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use BackedEnum;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\Common\EventManager;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\LockMode;
|
||||
use Doctrine\ORM\Exception\EntityManagerClosed;
|
||||
use Doctrine\ORM\Exception\InvalidHydrationMode;
|
||||
use Doctrine\ORM\Exception\MissingIdentifierField;
|
||||
use Doctrine\ORM\Exception\MissingMappingDriverImplementation;
|
||||
use Doctrine\ORM\Exception\ORMException;
|
||||
use Doctrine\ORM\Exception\UnrecognizedIdentifierFields;
|
||||
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\ORM\Proxy\ProxyFactory;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\Query\FilterCollection;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\ORM\Repository\RepositoryFactory;
|
||||
|
||||
use function array_keys;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function ltrim;
|
||||
use function method_exists;
|
||||
|
||||
/**
|
||||
* The EntityManager is the central access point to ORM functionality.
|
||||
*
|
||||
* It is a facade to all different ORM subsystems such as UnitOfWork,
|
||||
* Query Language and Repository API. The quickest way to obtain a fully
|
||||
* configured EntityManager is:
|
||||
*
|
||||
* use Doctrine\ORM\Tools\ORMSetup;
|
||||
* use Doctrine\ORM\EntityManager;
|
||||
*
|
||||
* $paths = ['/path/to/entity/mapping/files'];
|
||||
*
|
||||
* $config = ORMSetup::createAttributeMetadataConfig($paths);
|
||||
* $connection = DriverManager::getConnection(['driver' => 'pdo_sqlite', 'memory' => true], $config);
|
||||
* $entityManager = new EntityManager($connection, $config);
|
||||
*
|
||||
* For more information see
|
||||
* {@link http://docs.doctrine-project.org/projects/doctrine-orm/en/stable/reference/configuration.html}
|
||||
*
|
||||
* You should never attempt to inherit from the EntityManager: Inheritance
|
||||
* is not a valid extension point for the EntityManager. Instead you
|
||||
* should take a look at the {@see \Doctrine\ORM\Decorator\EntityManagerDecorator}
|
||||
* and wrap your entity manager in a decorator.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class EntityManager implements EntityManagerInterface
|
||||
{
|
||||
/**
|
||||
* The metadata factory, used to retrieve the ORM metadata of entity classes.
|
||||
*/
|
||||
private ClassMetadataFactory $metadataFactory;
|
||||
|
||||
/**
|
||||
* The UnitOfWork used to coordinate object-level transactions.
|
||||
*/
|
||||
private UnitOfWork $unitOfWork;
|
||||
|
||||
/**
|
||||
* The event manager that is the central point of the event system.
|
||||
*/
|
||||
private EventManager $eventManager;
|
||||
|
||||
/**
|
||||
* The proxy factory used to create dynamic proxies.
|
||||
*/
|
||||
private ProxyFactory $proxyFactory;
|
||||
|
||||
/**
|
||||
* The repository factory used to create dynamic repositories.
|
||||
*/
|
||||
private RepositoryFactory $repositoryFactory;
|
||||
|
||||
/**
|
||||
* The expression builder instance used to generate query expressions.
|
||||
*/
|
||||
private Expr|null $expressionBuilder = null;
|
||||
|
||||
/**
|
||||
* Whether the EntityManager is closed or not.
|
||||
*/
|
||||
private bool $closed = false;
|
||||
|
||||
/**
|
||||
* Collection of query filters.
|
||||
*/
|
||||
private FilterCollection|null $filterCollection = null;
|
||||
|
||||
/**
|
||||
* The second level cache regions API.
|
||||
*/
|
||||
private Cache|null $cache = null;
|
||||
|
||||
/**
|
||||
* Creates a new EntityManager that operates on the given database connection
|
||||
* and uses the given Configuration and EventManager implementations.
|
||||
*
|
||||
* @param Connection $conn The database connection used by the EntityManager.
|
||||
*/
|
||||
public function __construct(
|
||||
private Connection $conn,
|
||||
private Configuration $config,
|
||||
EventManager|null $eventManager = null,
|
||||
) {
|
||||
if (! $config->getMetadataDriverImpl()) {
|
||||
throw MissingMappingDriverImplementation::create();
|
||||
}
|
||||
|
||||
$this->eventManager = $eventManager
|
||||
?? (method_exists($conn, 'getEventManager')
|
||||
? $conn->getEventManager()
|
||||
: new EventManager()
|
||||
);
|
||||
|
||||
$metadataFactoryClassName = $config->getClassMetadataFactoryName();
|
||||
|
||||
$this->metadataFactory = new $metadataFactoryClassName();
|
||||
$this->metadataFactory->setEntityManager($this);
|
||||
|
||||
$this->configureMetadataCache();
|
||||
|
||||
$this->repositoryFactory = $config->getRepositoryFactory();
|
||||
$this->unitOfWork = new UnitOfWork($this);
|
||||
if ($config->isNativeLazyObjectsEnabled()) {
|
||||
$this->proxyFactory = new ProxyFactory($this);
|
||||
} else {
|
||||
$this->proxyFactory = new ProxyFactory(
|
||||
$this,
|
||||
$config->getProxyDir(),
|
||||
$config->getProxyNamespace(),
|
||||
$config->getAutoGenerateProxyClasses(),
|
||||
);
|
||||
}
|
||||
|
||||
if ($config->isSecondLevelCacheEnabled()) {
|
||||
$cacheConfig = $config->getSecondLevelCacheConfiguration();
|
||||
$cacheFactory = $cacheConfig->getCacheFactory();
|
||||
$this->cache = $cacheFactory->createCache($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getConnection(): Connection
|
||||
{
|
||||
return $this->conn;
|
||||
}
|
||||
|
||||
public function getMetadataFactory(): ClassMetadataFactory
|
||||
{
|
||||
return $this->metadataFactory;
|
||||
}
|
||||
|
||||
public function getExpressionBuilder(): Expr
|
||||
{
|
||||
return $this->expressionBuilder ??= new Expr();
|
||||
}
|
||||
|
||||
public function beginTransaction(): void
|
||||
{
|
||||
$this->conn->beginTransaction();
|
||||
}
|
||||
|
||||
public function getCache(): Cache|null
|
||||
{
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
public function wrapInTransaction(callable $func): mixed
|
||||
{
|
||||
$this->conn->beginTransaction();
|
||||
|
||||
$successful = false;
|
||||
|
||||
try {
|
||||
$return = $func($this);
|
||||
|
||||
$this->flush();
|
||||
$this->conn->commit();
|
||||
|
||||
$successful = true;
|
||||
|
||||
return $return;
|
||||
} finally {
|
||||
if (! $successful) {
|
||||
$this->close();
|
||||
if ($this->conn->isTransactionActive()) {
|
||||
$this->conn->rollBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function commit(): void
|
||||
{
|
||||
$this->conn->commit();
|
||||
}
|
||||
|
||||
public function rollback(): void
|
||||
{
|
||||
$this->conn->rollBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ORM metadata descriptor for a class.
|
||||
*
|
||||
* Internal note: Performance-sensitive method.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getClassMetadata(string $className): Mapping\ClassMetadata
|
||||
{
|
||||
return $this->metadataFactory->getMetadataFor($className);
|
||||
}
|
||||
|
||||
public function createQuery(string $dql = ''): Query
|
||||
{
|
||||
$query = new Query($this);
|
||||
|
||||
if (! empty($dql)) {
|
||||
$query->setDQL($dql);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function createNativeQuery(string $sql, ResultSetMapping $rsm): NativeQuery
|
||||
{
|
||||
$query = new NativeQuery($this);
|
||||
|
||||
$query->setSQL($sql);
|
||||
$query->setResultSetMapping($rsm);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function createQueryBuilder(): QueryBuilder
|
||||
{
|
||||
return new QueryBuilder($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes all changes to objects that have been queued up to now to the database.
|
||||
* This effectively synchronizes the in-memory state of managed objects with the
|
||||
* database.
|
||||
*
|
||||
* If an entity is explicitly passed to this method only this entity and
|
||||
* the cascade-persist semantics + scheduled inserts/removals are synchronized.
|
||||
*
|
||||
* @throws OptimisticLockException If a version check on an entity that
|
||||
* makes use of optimistic locking fails.
|
||||
* @throws ORMException
|
||||
*/
|
||||
public function flush(): void
|
||||
{
|
||||
$this->errorIfClosed();
|
||||
$this->unitOfWork->commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function find($className, mixed $id, LockMode|int|null $lockMode = null, int|null $lockVersion = null): object|null
|
||||
{
|
||||
$class = $this->metadataFactory->getMetadataFor(ltrim($className, '\\'));
|
||||
|
||||
if ($lockMode !== null) {
|
||||
$this->checkLockRequirements($lockMode, $class);
|
||||
}
|
||||
|
||||
if (! is_array($id)) {
|
||||
if ($class->isIdentifierComposite) {
|
||||
throw ORMInvalidArgumentException::invalidCompositeIdentifier();
|
||||
}
|
||||
|
||||
$id = [$class->identifier[0] => $id];
|
||||
}
|
||||
|
||||
foreach ($id as $i => $value) {
|
||||
if (is_object($value)) {
|
||||
$className = DefaultProxyClassNameResolver::getClass($value);
|
||||
if ($this->metadataFactory->hasMetadataFor($className)) {
|
||||
$id[$i] = $this->unitOfWork->getSingleIdentifierValue($value);
|
||||
|
||||
if ($id[$i] === null) {
|
||||
throw ORMInvalidArgumentException::invalidIdentifierBindingEntity($className);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sortedId = [];
|
||||
|
||||
foreach ($class->identifier as $identifier) {
|
||||
if (! isset($id[$identifier])) {
|
||||
throw MissingIdentifierField::fromFieldAndClass($identifier, $class->name);
|
||||
}
|
||||
|
||||
if ($id[$identifier] instanceof BackedEnum) {
|
||||
$sortedId[$identifier] = $id[$identifier]->value;
|
||||
} else {
|
||||
$sortedId[$identifier] = $id[$identifier];
|
||||
}
|
||||
|
||||
unset($id[$identifier]);
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
throw UnrecognizedIdentifierFields::fromClassAndFieldNames($class->name, array_keys($id));
|
||||
}
|
||||
|
||||
$unitOfWork = $this->getUnitOfWork();
|
||||
|
||||
$entity = $unitOfWork->tryGetById($sortedId, $class->rootEntityName);
|
||||
|
||||
// Check identity map first
|
||||
if ($entity !== false) {
|
||||
if (! ($entity instanceof $class->name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case $lockMode === LockMode::OPTIMISTIC:
|
||||
$this->lock($entity, $lockMode, $lockVersion);
|
||||
break;
|
||||
|
||||
case $lockMode === LockMode::NONE:
|
||||
case $lockMode === LockMode::PESSIMISTIC_READ:
|
||||
case $lockMode === LockMode::PESSIMISTIC_WRITE:
|
||||
$persister = $unitOfWork->getEntityPersister($class->name);
|
||||
$persister->refresh($sortedId, $entity, $lockMode);
|
||||
break;
|
||||
}
|
||||
|
||||
return $entity; // Hit!
|
||||
}
|
||||
|
||||
$persister = $unitOfWork->getEntityPersister($class->name);
|
||||
|
||||
switch (true) {
|
||||
case $lockMode === LockMode::OPTIMISTIC:
|
||||
$entity = $persister->load($sortedId);
|
||||
|
||||
if ($entity !== null) {
|
||||
$unitOfWork->lock($entity, $lockMode, $lockVersion);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
|
||||
case $lockMode === LockMode::PESSIMISTIC_READ:
|
||||
case $lockMode === LockMode::PESSIMISTIC_WRITE:
|
||||
return $persister->load($sortedId, null, null, [], $lockMode);
|
||||
|
||||
default:
|
||||
return $persister->loadById($sortedId);
|
||||
}
|
||||
}
|
||||
|
||||
public function getReference(string $entityName, mixed $id): object|null
|
||||
{
|
||||
$class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
|
||||
|
||||
if (! is_array($id)) {
|
||||
$id = [$class->identifier[0] => $id];
|
||||
}
|
||||
|
||||
$sortedId = [];
|
||||
|
||||
foreach ($class->identifier as $identifier) {
|
||||
if (! isset($id[$identifier])) {
|
||||
throw MissingIdentifierField::fromFieldAndClass($identifier, $class->name);
|
||||
}
|
||||
|
||||
$sortedId[$identifier] = $id[$identifier];
|
||||
unset($id[$identifier]);
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
throw UnrecognizedIdentifierFields::fromClassAndFieldNames($class->name, array_keys($id));
|
||||
}
|
||||
|
||||
$entity = $this->unitOfWork->tryGetById($sortedId, $class->rootEntityName);
|
||||
|
||||
// Check identity map first, if its already in there just return it.
|
||||
if ($entity !== false) {
|
||||
return $entity instanceof $class->name ? $entity : null;
|
||||
}
|
||||
|
||||
if ($class->subClasses) {
|
||||
return $this->find($entityName, $sortedId);
|
||||
}
|
||||
|
||||
$entity = $this->proxyFactory->getProxy($class->name, $sortedId);
|
||||
|
||||
$this->unitOfWork->registerManaged($entity, $sortedId, []);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the EntityManager. All entities that are currently managed
|
||||
* by this EntityManager become detached.
|
||||
*/
|
||||
public function clear(): void
|
||||
{
|
||||
$this->unitOfWork->clear();
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
$this->clear();
|
||||
|
||||
$this->closed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the EntityManager to make an instance managed and persistent.
|
||||
*
|
||||
* The entity will be entered into the database at or before transaction
|
||||
* commit or as a result of the flush operation.
|
||||
*
|
||||
* NOTE: The persist operation always considers entities that are not yet known to
|
||||
* this EntityManager as NEW. Do not pass detached entities to the persist operation.
|
||||
*
|
||||
* @throws ORMInvalidArgumentException
|
||||
* @throws ORMException
|
||||
*/
|
||||
public function persist(object $object): void
|
||||
{
|
||||
$this->errorIfClosed();
|
||||
|
||||
$this->unitOfWork->persist($object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an entity instance.
|
||||
*
|
||||
* A removed entity will be removed from the database at or before transaction commit
|
||||
* or as a result of the flush operation.
|
||||
*
|
||||
* @throws ORMInvalidArgumentException
|
||||
* @throws ORMException
|
||||
*/
|
||||
public function remove(object $object): void
|
||||
{
|
||||
$this->errorIfClosed();
|
||||
|
||||
$this->unitOfWork->remove($object);
|
||||
}
|
||||
|
||||
public function refresh(object $object, LockMode|int|null $lockMode = null): void
|
||||
{
|
||||
$this->errorIfClosed();
|
||||
|
||||
$this->unitOfWork->refresh($object, $lockMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches an entity from the EntityManager, causing a managed entity to
|
||||
* become detached. Unflushed changes made to the entity if any
|
||||
* (including removal of the entity), will not be synchronized to the database.
|
||||
* Entities which previously referenced the detached entity will continue to
|
||||
* reference it.
|
||||
*
|
||||
* @throws ORMInvalidArgumentException
|
||||
*/
|
||||
public function detach(object $object): void
|
||||
{
|
||||
$this->unitOfWork->detach($object);
|
||||
}
|
||||
|
||||
public function lock(object $entity, LockMode|int $lockMode, DateTimeInterface|int|null $lockVersion = null): void
|
||||
{
|
||||
$this->unitOfWork->lock($entity, $lockMode, $lockVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the repository for an entity class.
|
||||
*
|
||||
* @param class-string<T> $className The name of the entity.
|
||||
*
|
||||
* @return EntityRepository<T> The repository class.
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function getRepository(string $className): EntityRepository
|
||||
{
|
||||
return $this->repositoryFactory->getRepository($this, $className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether an entity instance is managed in this EntityManager.
|
||||
*
|
||||
* @return bool TRUE if this EntityManager currently manages the given entity, FALSE otherwise.
|
||||
*/
|
||||
public function contains(object $object): bool
|
||||
{
|
||||
return $this->unitOfWork->isScheduledForInsert($object)
|
||||
|| $this->unitOfWork->isInIdentityMap($object)
|
||||
&& ! $this->unitOfWork->isScheduledForDelete($object);
|
||||
}
|
||||
|
||||
public function getEventManager(): EventManager
|
||||
{
|
||||
return $this->eventManager;
|
||||
}
|
||||
|
||||
public function getConfiguration(): Configuration
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the EntityManager is closed or currently not active.
|
||||
*
|
||||
* @throws EntityManagerClosed If the EntityManager is closed.
|
||||
*/
|
||||
private function errorIfClosed(): void
|
||||
{
|
||||
if ($this->closed) {
|
||||
throw EntityManagerClosed::create();
|
||||
}
|
||||
}
|
||||
|
||||
public function isOpen(): bool
|
||||
{
|
||||
return ! $this->closed;
|
||||
}
|
||||
|
||||
public function getUnitOfWork(): UnitOfWork
|
||||
{
|
||||
return $this->unitOfWork;
|
||||
}
|
||||
|
||||
public function newHydrator(string|int $hydrationMode): AbstractHydrator
|
||||
{
|
||||
return match ($hydrationMode) {
|
||||
Query::HYDRATE_OBJECT => new Internal\Hydration\ObjectHydrator($this),
|
||||
Query::HYDRATE_ARRAY => new Internal\Hydration\ArrayHydrator($this),
|
||||
Query::HYDRATE_SCALAR => new Internal\Hydration\ScalarHydrator($this),
|
||||
Query::HYDRATE_SINGLE_SCALAR => new Internal\Hydration\SingleScalarHydrator($this),
|
||||
Query::HYDRATE_SIMPLEOBJECT => new Internal\Hydration\SimpleObjectHydrator($this),
|
||||
Query::HYDRATE_SCALAR_COLUMN => new Internal\Hydration\ScalarColumnHydrator($this),
|
||||
default => $this->createCustomHydrator((string) $hydrationMode),
|
||||
};
|
||||
}
|
||||
|
||||
public function getProxyFactory(): ProxyFactory
|
||||
{
|
||||
return $this->proxyFactory;
|
||||
}
|
||||
|
||||
public function initializeObject(object $obj): void
|
||||
{
|
||||
$this->unitOfWork->initializeObject($obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isUninitializedObject($value): bool
|
||||
{
|
||||
return $this->unitOfWork->isUninitializedObject($value);
|
||||
}
|
||||
|
||||
public function getFilters(): FilterCollection
|
||||
{
|
||||
return $this->filterCollection ??= new FilterCollection($this);
|
||||
}
|
||||
|
||||
public function isFiltersStateClean(): bool
|
||||
{
|
||||
return $this->filterCollection === null || $this->filterCollection->isClean();
|
||||
}
|
||||
|
||||
public function hasFilters(): bool
|
||||
{
|
||||
return $this->filterCollection !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param LockMode::* $lockMode
|
||||
*
|
||||
* @throws OptimisticLockException
|
||||
* @throws TransactionRequiredException
|
||||
*/
|
||||
private function checkLockRequirements(LockMode|int $lockMode, ClassMetadata $class): void
|
||||
{
|
||||
switch ($lockMode) {
|
||||
case LockMode::OPTIMISTIC:
|
||||
if (! $class->isVersioned) {
|
||||
throw OptimisticLockException::notVersioned($class->name);
|
||||
}
|
||||
|
||||
break;
|
||||
case LockMode::PESSIMISTIC_READ:
|
||||
case LockMode::PESSIMISTIC_WRITE:
|
||||
if (! $this->getConnection()->isTransactionActive()) {
|
||||
throw TransactionRequiredException::transactionRequired();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function configureMetadataCache(): void
|
||||
{
|
||||
$metadataCache = $this->config->getMetadataCache();
|
||||
if (! $metadataCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->metadataFactory->setCache($metadataCache);
|
||||
}
|
||||
|
||||
private function createCustomHydrator(string $hydrationMode): AbstractHydrator
|
||||
{
|
||||
$class = $this->config->getCustomHydrationMode($hydrationMode);
|
||||
|
||||
if ($class !== null) {
|
||||
return new $class($this);
|
||||
}
|
||||
|
||||
throw InvalidHydrationMode::fromMode($hydrationMode);
|
||||
}
|
||||
}
|
||||
241
backend/vendor/doctrine/orm/src/EntityManagerInterface.php
vendored
Normal file
241
backend/vendor/doctrine/orm/src/EntityManagerInterface.php
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Doctrine\Common\EventManager;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\LockMode;
|
||||
use Doctrine\ORM\Exception\ORMException;
|
||||
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\ORM\Proxy\ProxyFactory;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\Query\FilterCollection;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
interface EntityManagerInterface extends ObjectManager
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param class-string<T> $className
|
||||
*
|
||||
* @return EntityRepository<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function getRepository(string $className): EntityRepository;
|
||||
|
||||
/**
|
||||
* Returns the cache API for managing the second level cache regions or NULL if the cache is not enabled.
|
||||
*/
|
||||
public function getCache(): Cache|null;
|
||||
|
||||
/**
|
||||
* Gets the database connection object used by the EntityManager.
|
||||
*/
|
||||
public function getConnection(): Connection;
|
||||
|
||||
public function getMetadataFactory(): ClassMetadataFactory;
|
||||
|
||||
/**
|
||||
* Gets an ExpressionBuilder used for object-oriented construction of query expressions.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <code>
|
||||
* $qb = $em->createQueryBuilder();
|
||||
* $expr = $em->getExpressionBuilder();
|
||||
* $qb->select('u')->from('User', 'u')
|
||||
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
|
||||
* </code>
|
||||
*/
|
||||
public function getExpressionBuilder(): Expr;
|
||||
|
||||
/**
|
||||
* Starts a transaction on the underlying database connection.
|
||||
*/
|
||||
public function beginTransaction(): void;
|
||||
|
||||
/**
|
||||
* Executes a function in a transaction.
|
||||
*
|
||||
* The function gets passed this EntityManager instance as an (optional) parameter.
|
||||
*
|
||||
* {@link flush} is invoked prior to transaction commit.
|
||||
*
|
||||
* If an exception occurs during execution of the function or flushing or transaction commit,
|
||||
* the transaction is rolled back, the EntityManager closed and the exception re-thrown.
|
||||
*
|
||||
* @phpstan-param callable(self): T $func The function to execute transactionally.
|
||||
*
|
||||
* @return mixed The value returned from the closure.
|
||||
* @phpstan-return T
|
||||
*
|
||||
* @template T
|
||||
*/
|
||||
public function wrapInTransaction(callable $func): mixed;
|
||||
|
||||
/**
|
||||
* Commits a transaction on the underlying database connection.
|
||||
*/
|
||||
public function commit(): void;
|
||||
|
||||
/**
|
||||
* Performs a rollback on the underlying database connection.
|
||||
*/
|
||||
public function rollback(): void;
|
||||
|
||||
/**
|
||||
* Creates a new Query object.
|
||||
*
|
||||
* @param string $dql The DQL string.
|
||||
*/
|
||||
public function createQuery(string $dql = ''): Query;
|
||||
|
||||
/**
|
||||
* Creates a native SQL query.
|
||||
*/
|
||||
public function createNativeQuery(string $sql, ResultSetMapping $rsm): NativeQuery;
|
||||
|
||||
/**
|
||||
* Create a QueryBuilder instance
|
||||
*/
|
||||
public function createQueryBuilder(): QueryBuilder;
|
||||
|
||||
/**
|
||||
* Finds an Entity by its identifier.
|
||||
*
|
||||
* @param string $className The class name of the entity to find.
|
||||
* @param mixed $id The identity of the entity to find.
|
||||
* @param LockMode|int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants
|
||||
* or NULL if no specific lock mode should be used
|
||||
* during the search.
|
||||
* @param int|null $lockVersion The version of the entity to find when using
|
||||
* optimistic locking.
|
||||
* @phpstan-param class-string<T> $className
|
||||
* @phpstan-param LockMode::*|null $lockMode
|
||||
*
|
||||
* @return object|null The entity instance or NULL if the entity can not be found.
|
||||
* @phpstan-return T|null
|
||||
*
|
||||
* @throws OptimisticLockException
|
||||
* @throws ORMInvalidArgumentException
|
||||
* @throws TransactionRequiredException
|
||||
* @throws ORMException
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function find(string $className, mixed $id, LockMode|int|null $lockMode = null, int|null $lockVersion = null): object|null;
|
||||
|
||||
/**
|
||||
* Refreshes the persistent state of an object from the database,
|
||||
* overriding any local changes that have not yet been persisted.
|
||||
*
|
||||
* @param LockMode|int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants
|
||||
* or NULL if no specific lock mode should be used
|
||||
* during the search.
|
||||
* @phpstan-param LockMode::*|null $lockMode
|
||||
*
|
||||
* @throws ORMInvalidArgumentException
|
||||
* @throws ORMException
|
||||
* @throws TransactionRequiredException
|
||||
*/
|
||||
public function refresh(object $object, LockMode|int|null $lockMode = null): void;
|
||||
|
||||
/**
|
||||
* Gets a reference to the entity identified by the given type and identifier
|
||||
* without actually loading it, if the entity is not yet loaded.
|
||||
*
|
||||
* @param class-string<T> $entityName The name of the entity type.
|
||||
* @param mixed $id The entity identifier.
|
||||
*
|
||||
* @return T|null The entity reference.
|
||||
*
|
||||
* @throws ORMException
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function getReference(string $entityName, mixed $id): object|null;
|
||||
|
||||
/**
|
||||
* Closes the EntityManager. All entities that are currently managed
|
||||
* by this EntityManager become detached. The EntityManager may no longer
|
||||
* be used after it is closed.
|
||||
*/
|
||||
public function close(): void;
|
||||
|
||||
/**
|
||||
* Acquire a lock on the given entity.
|
||||
*
|
||||
* @phpstan-param LockMode::* $lockMode
|
||||
*
|
||||
* @throws OptimisticLockException
|
||||
* @throws PessimisticLockException
|
||||
*/
|
||||
public function lock(object $entity, LockMode|int $lockMode, DateTimeInterface|int|null $lockVersion = null): void;
|
||||
|
||||
/**
|
||||
* Gets the EventManager used by the EntityManager.
|
||||
*/
|
||||
public function getEventManager(): EventManager;
|
||||
|
||||
/**
|
||||
* Gets the Configuration used by the EntityManager.
|
||||
*/
|
||||
public function getConfiguration(): Configuration;
|
||||
|
||||
/**
|
||||
* Check if the Entity manager is open or closed.
|
||||
*/
|
||||
public function isOpen(): bool;
|
||||
|
||||
/**
|
||||
* Gets the UnitOfWork used by the EntityManager to coordinate operations.
|
||||
*/
|
||||
public function getUnitOfWork(): UnitOfWork;
|
||||
|
||||
/**
|
||||
* Create a new instance for the given hydration mode.
|
||||
*
|
||||
* @phpstan-param string|AbstractQuery::HYDRATE_* $hydrationMode
|
||||
*
|
||||
* @throws ORMException
|
||||
*/
|
||||
public function newHydrator(string|int $hydrationMode): AbstractHydrator;
|
||||
|
||||
/**
|
||||
* Gets the proxy factory used by the EntityManager to create entity proxies.
|
||||
*/
|
||||
public function getProxyFactory(): ProxyFactory;
|
||||
|
||||
/**
|
||||
* Gets the enabled filters.
|
||||
*/
|
||||
public function getFilters(): FilterCollection;
|
||||
|
||||
/**
|
||||
* Checks whether the state of the filter collection is clean.
|
||||
*/
|
||||
public function isFiltersStateClean(): bool;
|
||||
|
||||
/**
|
||||
* Checks whether the Entity Manager has filters.
|
||||
*/
|
||||
public function hasFilters(): bool;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param string|class-string<T> $className
|
||||
*
|
||||
* @phpstan-return ($className is class-string<T> ? Mapping\ClassMetadata<T> : Mapping\ClassMetadata<object>)
|
||||
*
|
||||
* @phpstan-template T of object
|
||||
*/
|
||||
public function getClassMetadata(string $className): Mapping\ClassMetadata;
|
||||
}
|
||||
46
backend/vendor/doctrine/orm/src/EntityNotFoundException.php
vendored
Normal file
46
backend/vendor/doctrine/orm/src/EntityNotFoundException.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\ORM\Exception\ORMException;
|
||||
use RuntimeException;
|
||||
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Exception thrown when a Proxy fails to retrieve an Entity result.
|
||||
*/
|
||||
class EntityNotFoundException extends RuntimeException implements ORMException
|
||||
{
|
||||
/**
|
||||
* Static constructor.
|
||||
*
|
||||
* @param string[] $id
|
||||
*/
|
||||
public static function fromClassNameAndIdentifier(string $className, array $id): self
|
||||
{
|
||||
$ids = [];
|
||||
|
||||
foreach ($id as $key => $value) {
|
||||
$ids[] = $key . '(' . $value . ')';
|
||||
}
|
||||
|
||||
return new self(
|
||||
'Entity of type \'' . $className . '\'' . ($ids ? ' for IDs ' . implode(', ', $ids) : '') . ' was not found',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instance for which no identifier can be found
|
||||
*/
|
||||
public static function noIdentifierFound(string $className): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Unable to find "%s" entity identifier associated with the UnitOfWork',
|
||||
$className,
|
||||
));
|
||||
}
|
||||
}
|
||||
237
backend/vendor/doctrine/orm/src/EntityRepository.php
vendored
Normal file
237
backend/vendor/doctrine/orm/src/EntityRepository.php
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Doctrine\Common\Collections\AbstractLazyCollection;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\Common\Collections\Selectable;
|
||||
use Doctrine\DBAL\LockMode;
|
||||
use Doctrine\Inflector\Inflector;
|
||||
use Doctrine\Inflector\InflectorFactory;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Query\ResultSetMappingBuilder;
|
||||
use Doctrine\ORM\Repository\Exception\InvalidMagicMethodCall;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
|
||||
use function array_slice;
|
||||
use function lcfirst;
|
||||
use function sprintf;
|
||||
use function str_starts_with;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* An EntityRepository serves as a repository for entities with generic as well as
|
||||
* business specific methods for retrieving entities.
|
||||
*
|
||||
* This class is designed for inheritance and users can subclass this class to
|
||||
* write their own repositories with business-specific methods to locate entities.
|
||||
*
|
||||
* @template T of object
|
||||
* @template-implements Selectable<int,T>
|
||||
* @template-implements ObjectRepository<T>
|
||||
*/
|
||||
class EntityRepository implements ObjectRepository, Selectable
|
||||
{
|
||||
/** @var class-string<T> */
|
||||
private readonly string $entityName;
|
||||
private static Inflector|null $inflector = null;
|
||||
|
||||
/** @param ClassMetadata<T> $class */
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly ClassMetadata $class,
|
||||
) {
|
||||
$this->entityName = $class->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new QueryBuilder instance that is prepopulated for this entity name.
|
||||
*/
|
||||
public function createQueryBuilder(string $alias, string|null $indexBy = null): QueryBuilder
|
||||
{
|
||||
return $this->em->createQueryBuilder()
|
||||
->select($alias)
|
||||
->from($this->entityName, $alias, $indexBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new result set mapping builder for this entity.
|
||||
*
|
||||
* The column naming strategy is "INCREMENT".
|
||||
*/
|
||||
public function createResultSetMappingBuilder(string $alias): ResultSetMappingBuilder
|
||||
{
|
||||
$rsm = new ResultSetMappingBuilder($this->em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT);
|
||||
$rsm->addRootEntityFromClassMetadata($this->entityName, $alias);
|
||||
|
||||
return $rsm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an entity by its primary key / identifier.
|
||||
*
|
||||
* @param LockMode|int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants
|
||||
* or NULL if no specific lock mode should be used
|
||||
* during the search.
|
||||
* @phpstan-param LockMode::*|null $lockMode
|
||||
*
|
||||
* @return object|null The entity instance or NULL if the entity can not be found.
|
||||
* @phpstan-return ?T
|
||||
*/
|
||||
public function find(mixed $id, LockMode|int|null $lockMode = null, int|null $lockVersion = null): object|null
|
||||
{
|
||||
return $this->em->find($this->entityName, $id, $lockMode, $lockVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all entities in the repository.
|
||||
*
|
||||
* @phpstan-return list<T> The entities.
|
||||
*/
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->findBy([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds entities by a set of criteria.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @phpstan-return list<T>
|
||||
*/
|
||||
public function findBy(array $criteria, array|null $orderBy = null, int|null $limit = null, int|null $offset = null): array
|
||||
{
|
||||
$persister = $this->em->getUnitOfWork()->getEntityPersister($this->entityName);
|
||||
|
||||
return $persister->loadAll($criteria, $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a single entity by a set of criteria.
|
||||
*
|
||||
* @phpstan-param array<string, mixed> $criteria
|
||||
* @phpstan-param array<string, string>|null $orderBy
|
||||
*
|
||||
* @phpstan-return T|null
|
||||
*/
|
||||
public function findOneBy(array $criteria, array|null $orderBy = null): object|null
|
||||
{
|
||||
$persister = $this->em->getUnitOfWork()->getEntityPersister($this->entityName);
|
||||
|
||||
return $persister->load($criteria, null, null, [], null, 1, $orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts entities by a set of criteria.
|
||||
*
|
||||
* @phpstan-param array<string, mixed> $criteria
|
||||
*
|
||||
* @return int The cardinality of the objects that match the given criteria.
|
||||
* @phpstan-return 0|positive-int
|
||||
*
|
||||
* @todo Add this method to `ObjectRepository` interface in the next major release
|
||||
*/
|
||||
public function count(array $criteria = []): int
|
||||
{
|
||||
return $this->em->getUnitOfWork()->getEntityPersister($this->entityName)->count($criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds support for magic method calls.
|
||||
*
|
||||
* @param mixed[] $arguments
|
||||
* @phpstan-param list<mixed> $arguments
|
||||
*
|
||||
* @throws BadMethodCallException If the method called is invalid.
|
||||
*/
|
||||
public function __call(string $method, array $arguments): mixed
|
||||
{
|
||||
if (str_starts_with($method, 'findBy')) {
|
||||
return $this->resolveMagicCall('findBy', substr($method, 6), $arguments);
|
||||
}
|
||||
|
||||
if (str_starts_with($method, 'findOneBy')) {
|
||||
return $this->resolveMagicCall('findOneBy', substr($method, 9), $arguments);
|
||||
}
|
||||
|
||||
if (str_starts_with($method, 'countBy')) {
|
||||
return $this->resolveMagicCall('count', substr($method, 7), $arguments);
|
||||
}
|
||||
|
||||
throw new BadMethodCallException(sprintf(
|
||||
'Undefined method "%s". The method name must start with ' .
|
||||
'either findBy, findOneBy or countBy!',
|
||||
$method,
|
||||
));
|
||||
}
|
||||
|
||||
/** @return class-string<T> */
|
||||
protected function getEntityName(): string
|
||||
{
|
||||
return $this->entityName;
|
||||
}
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return $this->getEntityName();
|
||||
}
|
||||
|
||||
protected function getEntityManager(): EntityManagerInterface
|
||||
{
|
||||
return $this->em;
|
||||
}
|
||||
|
||||
/** @phpstan-return ClassMetadata<T> */
|
||||
protected function getClassMetadata(): ClassMetadata
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all elements from a selectable that match the expression and
|
||||
* return a new collection containing these elements.
|
||||
*
|
||||
* @phpstan-return AbstractLazyCollection<int, T>&Selectable<int, T>
|
||||
*/
|
||||
public function matching(Criteria $criteria): AbstractLazyCollection&Selectable
|
||||
{
|
||||
$persister = $this->em->getUnitOfWork()->getEntityPersister($this->entityName);
|
||||
|
||||
return new LazyCriteriaCollection($persister, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a magic method call to the proper existent method at `EntityRepository`.
|
||||
*
|
||||
* @param string $method The method to call
|
||||
* @param string $by The property name used as condition
|
||||
* @phpstan-param list<mixed> $arguments The arguments to pass at method call
|
||||
*
|
||||
* @throws InvalidMagicMethodCall If the method called is invalid or the
|
||||
* requested field/association does not exist.
|
||||
*/
|
||||
private function resolveMagicCall(string $method, string $by, array $arguments): mixed
|
||||
{
|
||||
if (! $arguments) {
|
||||
throw InvalidMagicMethodCall::onMissingParameter($method . $by);
|
||||
}
|
||||
|
||||
self::$inflector ??= InflectorFactory::create()->build();
|
||||
|
||||
$fieldName = lcfirst(self::$inflector->classify($by));
|
||||
|
||||
if (! ($this->class->hasField($fieldName) || $this->class->hasAssociation($fieldName))) {
|
||||
throw InvalidMagicMethodCall::becauseFieldNotFoundIn(
|
||||
$this->entityName,
|
||||
$fieldName,
|
||||
$method . $by,
|
||||
);
|
||||
}
|
||||
|
||||
return $this->$method([$fieldName => $arguments[0]], ...array_slice($arguments, 1));
|
||||
}
|
||||
}
|
||||
98
backend/vendor/doctrine/orm/src/Event/ListenersInvoker.php
vendored
Normal file
98
backend/vendor/doctrine/orm/src/Event/ListenersInvoker.php
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\Common\EventArgs;
|
||||
use Doctrine\Common\EventManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\EntityListenerResolver;
|
||||
|
||||
/**
|
||||
* A method invoker based on entity lifecycle.
|
||||
*/
|
||||
class ListenersInvoker
|
||||
{
|
||||
final public const INVOKE_NONE = 0;
|
||||
final public const INVOKE_LISTENERS = 1;
|
||||
final public const INVOKE_CALLBACKS = 2;
|
||||
final public const INVOKE_MANAGER = 4;
|
||||
|
||||
/** The Entity listener resolver. */
|
||||
private readonly EntityListenerResolver $resolver;
|
||||
|
||||
/** The EventManager used for dispatching events. */
|
||||
private readonly EventManager $eventManager;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->eventManager = $em->getEventManager();
|
||||
$this->resolver = $em->getConfiguration()->getEntityListenerResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the subscribed event systems
|
||||
*
|
||||
* @param ClassMetadata $metadata The entity metadata.
|
||||
* @param string $eventName The entity lifecycle event.
|
||||
*
|
||||
* @phpstan-return int-mask-of<self::INVOKE_*> Bitmask of subscribed event systems.
|
||||
*/
|
||||
public function getSubscribedSystems(ClassMetadata $metadata, string $eventName): int
|
||||
{
|
||||
$invoke = self::INVOKE_NONE;
|
||||
|
||||
if (isset($metadata->lifecycleCallbacks[$eventName])) {
|
||||
$invoke |= self::INVOKE_CALLBACKS;
|
||||
}
|
||||
|
||||
if (isset($metadata->entityListeners[$eventName])) {
|
||||
$invoke |= self::INVOKE_LISTENERS;
|
||||
}
|
||||
|
||||
if ($this->eventManager->hasListeners($eventName)) {
|
||||
$invoke |= self::INVOKE_MANAGER;
|
||||
}
|
||||
|
||||
return $invoke;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the lifecycle event of the given entity.
|
||||
*
|
||||
* @param ClassMetadata $metadata The entity metadata.
|
||||
* @param string $eventName The entity lifecycle event.
|
||||
* @param object $entity The Entity on which the event occurred.
|
||||
* @param EventArgs $event The Event args.
|
||||
* @phpstan-param int-mask-of<self::INVOKE_*> $invoke Bitmask to invoke listeners.
|
||||
*/
|
||||
public function invoke(
|
||||
ClassMetadata $metadata,
|
||||
string $eventName,
|
||||
object $entity,
|
||||
EventArgs $event,
|
||||
int $invoke,
|
||||
): void {
|
||||
if ($invoke & self::INVOKE_CALLBACKS) {
|
||||
foreach ($metadata->lifecycleCallbacks[$eventName] as $callback) {
|
||||
$entity->$callback($event);
|
||||
}
|
||||
}
|
||||
|
||||
if ($invoke & self::INVOKE_LISTENERS) {
|
||||
foreach ($metadata->entityListeners[$eventName] as $listener) {
|
||||
$class = $listener['class'];
|
||||
$method = $listener['method'];
|
||||
$instance = $this->resolver->resolve($class);
|
||||
|
||||
$instance->$method($entity, $event);
|
||||
}
|
||||
}
|
||||
|
||||
if ($invoke & self::INVOKE_MANAGER) {
|
||||
$this->eventManager->dispatchEvent($eventName, $event);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
backend/vendor/doctrine/orm/src/Event/LoadClassMetadataEventArgs.php
vendored
Normal file
25
backend/vendor/doctrine/orm/src/Event/LoadClassMetadataEventArgs.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\Persistence\Event\LoadClassMetadataEventArgs as BaseLoadClassMetadataEventArgs;
|
||||
|
||||
/**
|
||||
* Class that holds event arguments for a loadMetadata event.
|
||||
*
|
||||
* @extends BaseLoadClassMetadataEventArgs<ClassMetadata<object>, EntityManagerInterface>
|
||||
*/
|
||||
class LoadClassMetadataEventArgs extends BaseLoadClassMetadataEventArgs
|
||||
{
|
||||
/**
|
||||
* Retrieve associated EntityManager.
|
||||
*/
|
||||
public function getEntityManager(): EntityManagerInterface
|
||||
{
|
||||
return $this->getObjectManager();
|
||||
}
|
||||
}
|
||||
49
backend/vendor/doctrine/orm/src/Event/OnClassMetadataNotFoundEventArgs.php
vendored
Normal file
49
backend/vendor/doctrine/orm/src/Event/OnClassMetadataNotFoundEventArgs.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\ManagerEventArgs;
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
/**
|
||||
* Class that holds event arguments for a `onClassMetadataNotFound` event.
|
||||
*
|
||||
* This object is mutable by design, allowing callbacks having access to it to set the
|
||||
* found metadata in it, and therefore "cancelling" a `onClassMetadataNotFound` event
|
||||
*
|
||||
* @extends ManagerEventArgs<EntityManagerInterface>
|
||||
*/
|
||||
class OnClassMetadataNotFoundEventArgs extends ManagerEventArgs
|
||||
{
|
||||
private ClassMetadata|null $foundMetadata = null;
|
||||
|
||||
/** @param EntityManagerInterface $objectManager */
|
||||
public function __construct(
|
||||
private readonly string $className,
|
||||
ObjectManager $objectManager,
|
||||
) {
|
||||
parent::__construct($objectManager);
|
||||
}
|
||||
|
||||
public function setFoundMetadata(ClassMetadata|null $classMetadata): void
|
||||
{
|
||||
$this->foundMetadata = $classMetadata;
|
||||
}
|
||||
|
||||
public function getFoundMetadata(): ClassMetadata|null
|
||||
{
|
||||
return $this->foundMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve class name for which a failed metadata fetch attempt was executed
|
||||
*/
|
||||
public function getClassName(): string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
}
|
||||
19
backend/vendor/doctrine/orm/src/Event/OnClearEventArgs.php
vendored
Normal file
19
backend/vendor/doctrine/orm/src/Event/OnClearEventArgs.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\OnClearEventArgs as BaseOnClearEventArgs;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the onClear event.
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
*
|
||||
* @extends BaseOnClearEventArgs<EntityManagerInterface>
|
||||
*/
|
||||
class OnClearEventArgs extends BaseOnClearEventArgs
|
||||
{
|
||||
}
|
||||
19
backend/vendor/doctrine/orm/src/Event/OnFlushEventArgs.php
vendored
Normal file
19
backend/vendor/doctrine/orm/src/Event/OnFlushEventArgs.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\ManagerEventArgs;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the preFlush event.
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
*
|
||||
* @extends ManagerEventArgs<EntityManagerInterface>
|
||||
*/
|
||||
class OnFlushEventArgs extends ManagerEventArgs
|
||||
{
|
||||
}
|
||||
19
backend/vendor/doctrine/orm/src/Event/PostFlushEventArgs.php
vendored
Normal file
19
backend/vendor/doctrine/orm/src/Event/PostFlushEventArgs.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\ManagerEventArgs;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the postFlush event.
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
*
|
||||
* @extends ManagerEventArgs<EntityManagerInterface>
|
||||
*/
|
||||
class PostFlushEventArgs extends ManagerEventArgs
|
||||
{
|
||||
}
|
||||
13
backend/vendor/doctrine/orm/src/Event/PostLoadEventArgs.php
vendored
Normal file
13
backend/vendor/doctrine/orm/src/Event/PostLoadEventArgs.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
|
||||
/** @extends LifecycleEventArgs<EntityManagerInterface> */
|
||||
final class PostLoadEventArgs extends LifecycleEventArgs
|
||||
{
|
||||
}
|
||||
13
backend/vendor/doctrine/orm/src/Event/PostPersistEventArgs.php
vendored
Normal file
13
backend/vendor/doctrine/orm/src/Event/PostPersistEventArgs.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
|
||||
/** @extends LifecycleEventArgs<EntityManagerInterface> */
|
||||
final class PostPersistEventArgs extends LifecycleEventArgs
|
||||
{
|
||||
}
|
||||
13
backend/vendor/doctrine/orm/src/Event/PostRemoveEventArgs.php
vendored
Normal file
13
backend/vendor/doctrine/orm/src/Event/PostRemoveEventArgs.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
|
||||
/** @extends LifecycleEventArgs<EntityManagerInterface> */
|
||||
final class PostRemoveEventArgs extends LifecycleEventArgs
|
||||
{
|
||||
}
|
||||
13
backend/vendor/doctrine/orm/src/Event/PostUpdateEventArgs.php
vendored
Normal file
13
backend/vendor/doctrine/orm/src/Event/PostUpdateEventArgs.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
|
||||
/** @extends LifecycleEventArgs<EntityManagerInterface> */
|
||||
final class PostUpdateEventArgs extends LifecycleEventArgs
|
||||
{
|
||||
}
|
||||
19
backend/vendor/doctrine/orm/src/Event/PreFlushEventArgs.php
vendored
Normal file
19
backend/vendor/doctrine/orm/src/Event/PreFlushEventArgs.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\ManagerEventArgs;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the preFlush event.
|
||||
*
|
||||
* @link www.doctrine-project.com
|
||||
*
|
||||
* @extends ManagerEventArgs<EntityManagerInterface>
|
||||
*/
|
||||
class PreFlushEventArgs extends ManagerEventArgs
|
||||
{
|
||||
}
|
||||
13
backend/vendor/doctrine/orm/src/Event/PrePersistEventArgs.php
vendored
Normal file
13
backend/vendor/doctrine/orm/src/Event/PrePersistEventArgs.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
|
||||
/** @extends LifecycleEventArgs<EntityManagerInterface> */
|
||||
final class PrePersistEventArgs extends LifecycleEventArgs
|
||||
{
|
||||
}
|
||||
13
backend/vendor/doctrine/orm/src/Event/PreRemoveEventArgs.php
vendored
Normal file
13
backend/vendor/doctrine/orm/src/Event/PreRemoveEventArgs.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
|
||||
/** @extends LifecycleEventArgs<EntityManagerInterface> */
|
||||
final class PreRemoveEventArgs extends LifecycleEventArgs
|
||||
{
|
||||
}
|
||||
100
backend/vendor/doctrine/orm/src/Event/PreUpdateEventArgs.php
vendored
Normal file
100
backend/vendor/doctrine/orm/src/Event/PreUpdateEventArgs.php
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
use InvalidArgumentException;
|
||||
|
||||
use function get_debug_type;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Class that holds event arguments for a preUpdate event.
|
||||
*
|
||||
* @extends LifecycleEventArgs<EntityManagerInterface>
|
||||
*/
|
||||
class PreUpdateEventArgs extends LifecycleEventArgs
|
||||
{
|
||||
/** @var array<string, array{mixed, mixed}|PersistentCollection> */
|
||||
private array $entityChangeSet;
|
||||
|
||||
/**
|
||||
* @param mixed[][] $changeSet
|
||||
* @phpstan-param array<string, array{mixed, mixed}|PersistentCollection> $changeSet
|
||||
*/
|
||||
public function __construct(object $entity, EntityManagerInterface $em, array &$changeSet)
|
||||
{
|
||||
parent::__construct($entity, $em);
|
||||
|
||||
$this->entityChangeSet = &$changeSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves entity changeset.
|
||||
*
|
||||
* @return mixed[][]
|
||||
* @phpstan-return array<string, array{mixed, mixed}|PersistentCollection>
|
||||
*/
|
||||
public function getEntityChangeSet(): array
|
||||
{
|
||||
return $this->entityChangeSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if field has a changeset.
|
||||
*/
|
||||
public function hasChangedField(string $field): bool
|
||||
{
|
||||
return isset($this->entityChangeSet[$field]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the old value of the changeset of the changed field.
|
||||
*/
|
||||
public function getOldValue(string $field): mixed
|
||||
{
|
||||
$this->assertValidField($field);
|
||||
|
||||
return $this->entityChangeSet[$field][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new value of the changeset of the changed field.
|
||||
*/
|
||||
public function getNewValue(string $field): mixed
|
||||
{
|
||||
$this->assertValidField($field);
|
||||
|
||||
return $this->entityChangeSet[$field][1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new value of this field.
|
||||
*/
|
||||
public function setNewValue(string $field, mixed $value): void
|
||||
{
|
||||
$this->assertValidField($field);
|
||||
|
||||
$this->entityChangeSet[$field][1] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the field exists in changeset.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function assertValidField(string $field): void
|
||||
{
|
||||
if (! isset($this->entityChangeSet[$field])) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.',
|
||||
$field,
|
||||
get_debug_type($this->getObject()),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
123
backend/vendor/doctrine/orm/src/Events.php
vendored
Normal file
123
backend/vendor/doctrine/orm/src/Events.php
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
/**
|
||||
* Container for all ORM events.
|
||||
*
|
||||
* This class cannot be instantiated.
|
||||
*/
|
||||
final class Events
|
||||
{
|
||||
/**
|
||||
* Private constructor. This class is not meant to be instantiated.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* The preRemove event occurs for a given entity before the respective
|
||||
* EntityManager remove operation for that entity is executed.
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*/
|
||||
public const preRemove = 'preRemove';
|
||||
|
||||
/**
|
||||
* The postRemove event occurs for an entity after the entity has
|
||||
* been deleted. It will be invoked after the database delete operations.
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*/
|
||||
public const postRemove = 'postRemove';
|
||||
|
||||
/**
|
||||
* The prePersist event occurs for a given entity before the respective
|
||||
* EntityManager persist operation for that entity is executed.
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*/
|
||||
public const prePersist = 'prePersist';
|
||||
|
||||
/**
|
||||
* The postPersist event occurs for an entity after the entity has
|
||||
* been made persistent. It will be invoked after the database insert operations.
|
||||
* Generated primary key values are available in the postPersist event.
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*/
|
||||
public const postPersist = 'postPersist';
|
||||
|
||||
/**
|
||||
* The preUpdate event occurs before the database update operations to
|
||||
* entity data.
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*/
|
||||
public const preUpdate = 'preUpdate';
|
||||
|
||||
/**
|
||||
* The postUpdate event occurs after the database update operations to
|
||||
* entity data.
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*/
|
||||
public const postUpdate = 'postUpdate';
|
||||
|
||||
/**
|
||||
* The postLoad event occurs for an entity after the entity has been loaded
|
||||
* into the current EntityManager from the database or after the refresh operation
|
||||
* has been applied to it.
|
||||
*
|
||||
* Note that the postLoad event occurs for an entity before any associations have been
|
||||
* initialized. Therefore, it is not safe to access associations in a postLoad callback
|
||||
* or event handler.
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*/
|
||||
public const postLoad = 'postLoad';
|
||||
|
||||
/**
|
||||
* The loadClassMetadata event occurs after the mapping metadata for a class
|
||||
* has been loaded from a mapping source (attributes/xml).
|
||||
*/
|
||||
public const loadClassMetadata = 'loadClassMetadata';
|
||||
|
||||
/**
|
||||
* The onClassMetadataNotFound event occurs whenever loading metadata for a class
|
||||
* failed.
|
||||
*/
|
||||
public const onClassMetadataNotFound = 'onClassMetadataNotFound';
|
||||
|
||||
/**
|
||||
* The preFlush event occurs when the EntityManager#flush() operation is invoked,
|
||||
* but before any changes to managed entities have been calculated. This event is
|
||||
* always raised right after EntityManager#flush() call.
|
||||
*/
|
||||
public const preFlush = 'preFlush';
|
||||
|
||||
/**
|
||||
* The onFlush event occurs when the EntityManager#flush() operation is invoked,
|
||||
* after any changes to managed entities have been determined but before any
|
||||
* actual database operations are executed. The event is only raised if there is
|
||||
* actually something to do for the underlying UnitOfWork.
|
||||
*/
|
||||
public const onFlush = 'onFlush';
|
||||
|
||||
/**
|
||||
* The postFlush event occurs when the EntityManager#flush() operation is invoked and
|
||||
* after all actual database operations are executed successfully. The event is only raised if there is
|
||||
* actually something to do for the underlying UnitOfWork. The event won't be raised if an error occurs during the
|
||||
* flush operation.
|
||||
*/
|
||||
public const postFlush = 'postFlush';
|
||||
|
||||
/**
|
||||
* The onClear event occurs when the EntityManager#clear() operation is invoked,
|
||||
* after all references to entities have been removed from the unit of work.
|
||||
*/
|
||||
public const onClear = 'onClear';
|
||||
}
|
||||
9
backend/vendor/doctrine/orm/src/Exception/ConfigurationException.php
vendored
Normal file
9
backend/vendor/doctrine/orm/src/Exception/ConfigurationException.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
interface ConfigurationException extends ORMException
|
||||
{
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Exception/DuplicateFieldException.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Exception/DuplicateFieldException.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class DuplicateFieldException extends LogicException implements ORMException
|
||||
{
|
||||
public static function create(string $argName, string $columnName): self
|
||||
{
|
||||
return new self(sprintf('Name "%s" for "%s" already in use.', $argName, $columnName));
|
||||
}
|
||||
}
|
||||
39
backend/vendor/doctrine/orm/src/Exception/EntityIdentityCollisionException.php
vendored
Normal file
39
backend/vendor/doctrine/orm/src/Exception/EntityIdentityCollisionException.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
final class EntityIdentityCollisionException extends Exception implements ORMException
|
||||
{
|
||||
public static function create(object $existingEntity, object $newEntity, string $idHash): self
|
||||
{
|
||||
return new self(
|
||||
sprintf(
|
||||
<<<'EXCEPTION'
|
||||
While adding an entity of class %s with an ID hash of "%s" to the identity map,
|
||||
another object of class %s was already present for the same ID. This exception
|
||||
is a safeguard against an internal inconsistency - IDs should uniquely map to
|
||||
entity object instances. This problem may occur if:
|
||||
|
||||
- you use application-provided IDs and reuse ID values;
|
||||
- database-provided IDs are reassigned after truncating the database without
|
||||
clearing the EntityManager;
|
||||
- you might have been using EntityManager#getReference() to create a reference
|
||||
for a nonexistent ID that was subsequently (by the RDBMS) assigned to another
|
||||
entity.
|
||||
|
||||
Otherwise, it might be an ORM-internal inconsistency, please report it.
|
||||
EXCEPTION
|
||||
,
|
||||
$newEntity::class,
|
||||
$idHash,
|
||||
$existingEntity::class,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
15
backend/vendor/doctrine/orm/src/Exception/EntityManagerClosed.php
vendored
Normal file
15
backend/vendor/doctrine/orm/src/Exception/EntityManagerClosed.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class EntityManagerClosed extends RuntimeException implements ManagerException
|
||||
{
|
||||
public static function create(): self
|
||||
{
|
||||
return new self('The EntityManager is closed.');
|
||||
}
|
||||
}
|
||||
20
backend/vendor/doctrine/orm/src/Exception/EntityMissingAssignedId.php
vendored
Normal file
20
backend/vendor/doctrine/orm/src/Exception/EntityMissingAssignedId.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
use function get_debug_type;
|
||||
|
||||
final class EntityMissingAssignedId extends LogicException implements ORMException
|
||||
{
|
||||
public static function forField(object $entity, string $field): self
|
||||
{
|
||||
return new self('Entity of type ' . get_debug_type($entity) . " is missing an assigned ID for field '" . $field . "'. " .
|
||||
'The identifier generation strategy for this entity requires the ID field to be populated before ' .
|
||||
'EntityManager#persist() is called. If you want automatically generated identifiers instead ' .
|
||||
'you need to adjust the metadata mapping accordingly.');
|
||||
}
|
||||
}
|
||||
18
backend/vendor/doctrine/orm/src/Exception/InvalidEntityRepository.php
vendored
Normal file
18
backend/vendor/doctrine/orm/src/Exception/InvalidEntityRepository.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use LogicException;
|
||||
|
||||
final class InvalidEntityRepository extends LogicException implements ConfigurationException
|
||||
{
|
||||
public static function fromClassName(string $className): self
|
||||
{
|
||||
return new self(
|
||||
"Invalid repository class '" . $className . "'. It must be a " . EntityRepository::class . '.',
|
||||
);
|
||||
}
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Exception/InvalidHydrationMode.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Exception/InvalidHydrationMode.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
final class InvalidHydrationMode extends LogicException implements ManagerException
|
||||
{
|
||||
public static function fromMode(string $mode): self
|
||||
{
|
||||
return new self(sprintf('"%s" is an invalid hydration mode.', $mode));
|
||||
}
|
||||
}
|
||||
11
backend/vendor/doctrine/orm/src/Exception/ManagerException.php
vendored
Normal file
11
backend/vendor/doctrine/orm/src/Exception/ManagerException.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
interface ManagerException extends Throwable
|
||||
{
|
||||
}
|
||||
21
backend/vendor/doctrine/orm/src/Exception/MissingIdentifierField.php
vendored
Normal file
21
backend/vendor/doctrine/orm/src/Exception/MissingIdentifierField.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
final class MissingIdentifierField extends LogicException implements ManagerException
|
||||
{
|
||||
public static function fromFieldAndClass(string $fieldName, string $className): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The identifier %s is missing for a query of %s',
|
||||
$fieldName,
|
||||
$className,
|
||||
));
|
||||
}
|
||||
}
|
||||
18
backend/vendor/doctrine/orm/src/Exception/MissingMappingDriverImplementation.php
vendored
Normal file
18
backend/vendor/doctrine/orm/src/Exception/MissingMappingDriverImplementation.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
final class MissingMappingDriverImplementation extends LogicException implements ManagerException
|
||||
{
|
||||
public static function create(): self
|
||||
{
|
||||
return new self(
|
||||
"It's a requirement to specify a Metadata Driver and pass it " .
|
||||
'to Doctrine\\ORM\\Configuration::setMetadataDriverImpl().',
|
||||
);
|
||||
}
|
||||
}
|
||||
26
backend/vendor/doctrine/orm/src/Exception/MultipleSelectorsFoundException.php
vendored
Normal file
26
backend/vendor/doctrine/orm/src/Exception/MultipleSelectorsFoundException.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
|
||||
final class MultipleSelectorsFoundException extends LogicException implements ORMException
|
||||
{
|
||||
public const MULTIPLE_SELECTORS_FOUND_EXCEPTION = 'Multiple selectors found: %s. Please select only one.';
|
||||
|
||||
/** @param string[] $selectors */
|
||||
public static function create(array $selectors): self
|
||||
{
|
||||
return new self(
|
||||
sprintf(
|
||||
self::MULTIPLE_SELECTORS_FOUND_EXCEPTION,
|
||||
implode(', ', $selectors),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Exception/NoMatchingPropertyException.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Exception/NoMatchingPropertyException.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class NoMatchingPropertyException extends LogicException implements ORMException
|
||||
{
|
||||
public static function create(string $property): self
|
||||
{
|
||||
return new self(sprintf('Column name "%s" does not match any property name. Consider aliasing it to the name of an existing property.', $property));
|
||||
}
|
||||
}
|
||||
44
backend/vendor/doctrine/orm/src/Exception/NotSupported.php
vendored
Normal file
44
backend/vendor/doctrine/orm/src/Exception/NotSupported.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/** @deprecated */
|
||||
final class NotSupported extends LogicException implements ORMException
|
||||
{
|
||||
public static function create(): self
|
||||
{
|
||||
return new self('This behaviour is (currently) not supported by Doctrine 2');
|
||||
}
|
||||
|
||||
public static function createForDbal3(string $context): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
<<<'EXCEPTION'
|
||||
Context: %s
|
||||
Problem: Feature was deprecated in doctrine/dbal 2.x and is not supported by installed doctrine/dbal:3.x
|
||||
Solution: See the doctrine/deprecations logs for new alternative approaches.
|
||||
EXCEPTION
|
||||
,
|
||||
$context,
|
||||
));
|
||||
}
|
||||
|
||||
public static function createForPersistence3(string $context): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
<<<'EXCEPTION'
|
||||
Context: %s
|
||||
Problem: Feature was deprecated in doctrine/persistence 2.x and is not supported by installed doctrine/persistence:3.x
|
||||
Solution: See the doctrine/deprecations logs for new alternative approaches.
|
||||
EXCEPTION
|
||||
,
|
||||
$context,
|
||||
));
|
||||
}
|
||||
}
|
||||
11
backend/vendor/doctrine/orm/src/Exception/ORMException.php
vendored
Normal file
11
backend/vendor/doctrine/orm/src/Exception/ORMException.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
interface ORMException extends Throwable
|
||||
{
|
||||
}
|
||||
11
backend/vendor/doctrine/orm/src/Exception/PersisterException.php
vendored
Normal file
11
backend/vendor/doctrine/orm/src/Exception/PersisterException.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use Doctrine\ORM\Persisters\PersisterException as BasePersisterException;
|
||||
|
||||
class PersisterException extends BasePersisterException
|
||||
{
|
||||
}
|
||||
13
backend/vendor/doctrine/orm/src/Exception/RepositoryException.php
vendored
Normal file
13
backend/vendor/doctrine/orm/src/Exception/RepositoryException.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
/**
|
||||
* This interface should be implemented by all exceptions in the Repository
|
||||
* namespace.
|
||||
*/
|
||||
interface RepositoryException extends ORMException
|
||||
{
|
||||
}
|
||||
11
backend/vendor/doctrine/orm/src/Exception/SchemaToolException.php
vendored
Normal file
11
backend/vendor/doctrine/orm/src/Exception/SchemaToolException.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
interface SchemaToolException extends Throwable
|
||||
{
|
||||
}
|
||||
27
backend/vendor/doctrine/orm/src/Exception/UnexpectedAssociationValue.php
vendored
Normal file
27
backend/vendor/doctrine/orm/src/Exception/UnexpectedAssociationValue.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Exception;
|
||||
|
||||
use Doctrine\ORM\Cache\Exception\CacheException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
final class UnexpectedAssociationValue extends CacheException
|
||||
{
|
||||
public static function create(
|
||||
string $class,
|
||||
string $association,
|
||||
string $given,
|
||||
string $expected,
|
||||
): self {
|
||||
return new self(sprintf(
|
||||
'Found entity of type %s on association %s#%s, but expecting %s',
|
||||
$given,
|
||||
$class,
|
||||
$association,
|
||||
$expected,
|
||||
));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user