init
This commit is contained in:
76
backend/vendor/doctrine/orm/src/Mapping/AnsiQuoteStrategy.php
vendored
Normal file
76
backend/vendor/doctrine/orm/src/Mapping/AnsiQuoteStrategy.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\ORM\Internal\SQLResultCasing;
|
||||
|
||||
/**
|
||||
* ANSI compliant quote strategy, this strategy does not apply any quote.
|
||||
* To use this strategy all mapped tables and columns should be ANSI compliant.
|
||||
*/
|
||||
class AnsiQuoteStrategy implements QuoteStrategy
|
||||
{
|
||||
use SQLResultCasing;
|
||||
|
||||
public function getColumnName(
|
||||
string $fieldName,
|
||||
ClassMetadata $class,
|
||||
AbstractPlatform $platform,
|
||||
): string {
|
||||
return $class->fieldMappings[$fieldName]->columnName;
|
||||
}
|
||||
|
||||
public function getTableName(ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
return $class->table['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
return $definition['sequenceName'];
|
||||
}
|
||||
|
||||
public function getJoinColumnName(JoinColumnMapping $joinColumn, ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
return $joinColumn->name;
|
||||
}
|
||||
|
||||
public function getReferencedJoinColumnName(
|
||||
JoinColumnMapping $joinColumn,
|
||||
ClassMetadata $class,
|
||||
AbstractPlatform $platform,
|
||||
): string {
|
||||
return $joinColumn->referencedColumnName;
|
||||
}
|
||||
|
||||
public function getJoinTableName(
|
||||
ManyToManyOwningSideMapping $association,
|
||||
ClassMetadata $class,
|
||||
AbstractPlatform $platform,
|
||||
): string {
|
||||
return $association->joinTable->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform): array
|
||||
{
|
||||
return $class->identifier;
|
||||
}
|
||||
|
||||
public function getColumnAlias(
|
||||
string $columnName,
|
||||
int $counter,
|
||||
AbstractPlatform $platform,
|
||||
ClassMetadata|null $class = null,
|
||||
): string {
|
||||
return $this->getSQLResultCasing($platform, $columnName . '_' . $counter);
|
||||
}
|
||||
}
|
||||
70
backend/vendor/doctrine/orm/src/Mapping/ArrayAccessImplementation.php
vendored
Normal file
70
backend/vendor/doctrine/orm/src/Mapping/ArrayAccessImplementation.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use InvalidArgumentException;
|
||||
|
||||
use function property_exists;
|
||||
|
||||
/** @internal */
|
||||
trait ArrayAccessImplementation
|
||||
{
|
||||
/** @param string $offset */
|
||||
public function offsetExists(mixed $offset): bool
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/11211',
|
||||
'Using ArrayAccess on %s is deprecated and will not be possible in Doctrine ORM 4.0. Use the corresponding property instead.',
|
||||
static::class,
|
||||
);
|
||||
|
||||
return isset($this->$offset);
|
||||
}
|
||||
|
||||
/** @param string $offset */
|
||||
public function offsetGet(mixed $offset): mixed
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/11211',
|
||||
'Using ArrayAccess on %s is deprecated and will not be possible in Doctrine ORM 4.0. Use the corresponding property instead.',
|
||||
static::class,
|
||||
);
|
||||
|
||||
if (! property_exists($this, $offset)) {
|
||||
throw new InvalidArgumentException('Undefined property: ' . $offset);
|
||||
}
|
||||
|
||||
return $this->$offset;
|
||||
}
|
||||
|
||||
/** @param string $offset */
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/11211',
|
||||
'Using ArrayAccess on %s is deprecated and will not be possible in Doctrine ORM 4.0. Use the corresponding property instead.',
|
||||
static::class,
|
||||
);
|
||||
|
||||
$this->$offset = $value;
|
||||
}
|
||||
|
||||
/** @param string $offset */
|
||||
public function offsetUnset(mixed $offset): void
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/11211',
|
||||
'Using ArrayAccess on %s is deprecated and will not be possible in Doctrine ORM 4.0. Use the corresponding property instead.',
|
||||
static::class,
|
||||
);
|
||||
|
||||
$this->$offset = null;
|
||||
}
|
||||
}
|
||||
365
backend/vendor/doctrine/orm/src/Mapping/AssociationMapping.php
vendored
Normal file
365
backend/vendor/doctrine/orm/src/Mapping/AssociationMapping.php
vendored
Normal file
@@ -0,0 +1,365 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use ArrayAccess;
|
||||
use Exception;
|
||||
use OutOfRangeException;
|
||||
|
||||
use function assert;
|
||||
use function count;
|
||||
use function in_array;
|
||||
use function property_exists;
|
||||
use function sprintf;
|
||||
|
||||
/** @template-implements ArrayAccess<string, mixed> */
|
||||
abstract class AssociationMapping implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* The names of persistence operations to cascade on the association.
|
||||
*
|
||||
* @var list<'persist'|'remove'|'detach'|'refresh'|'all'>
|
||||
*/
|
||||
public array $cascade = [];
|
||||
|
||||
/**
|
||||
* The fetching strategy to use for the association, usually defaults to FETCH_LAZY.
|
||||
*
|
||||
* @var ClassMetadata::FETCH_*|null
|
||||
*/
|
||||
public int|null $fetch = null;
|
||||
|
||||
/**
|
||||
* This is set when the association is inherited by this class from another
|
||||
* (inheritance) parent <em>entity</em> class. The value is the FQCN of the
|
||||
* topmost entity class that contains this association. (If there are
|
||||
* transient classes in the class hierarchy, these are ignored, so the
|
||||
* class property may in fact come from a class further up in the PHP class
|
||||
* hierarchy.) To-many associations initially declared in mapped
|
||||
* superclasses are <em>not</em> considered 'inherited' in the nearest
|
||||
* entity subclasses.
|
||||
*
|
||||
* @var class-string|null
|
||||
*/
|
||||
public string|null $inherited = null;
|
||||
|
||||
/**
|
||||
* This is set when the association does not appear in the current class
|
||||
* for the first time, but is initially declared in another parent
|
||||
* <em>entity or mapped superclass</em>. The value is the FQCN of the
|
||||
* topmost non-transient class that contains association information for
|
||||
* this relationship.
|
||||
*
|
||||
* @var class-string|null
|
||||
*/
|
||||
public string|null $declared = null;
|
||||
|
||||
public array|null $cache = null;
|
||||
|
||||
public bool|null $id = null;
|
||||
|
||||
public bool|null $isOnDeleteCascade = null;
|
||||
|
||||
/** @var class-string|null */
|
||||
public string|null $originalClass = null;
|
||||
|
||||
public string|null $originalField = null;
|
||||
|
||||
public bool $orphanRemoval = false;
|
||||
|
||||
public bool|null $unique = null;
|
||||
|
||||
/**
|
||||
* @param string $fieldName The name of the field in the entity
|
||||
* the association is mapped to.
|
||||
* @param class-string $sourceEntity The class name of the source entity.
|
||||
* In the case of to-many associations
|
||||
* initially present in mapped
|
||||
* superclasses, the nearest
|
||||
* <em>entity</em> subclasses will be
|
||||
* considered the respective source
|
||||
* entities.
|
||||
* @param class-string $targetEntity The class name of the target entity.
|
||||
* If it is fully-qualified it is used as
|
||||
* is. If it is a simple, unqualified
|
||||
* class name the namespace is assumed to
|
||||
* be the same as the namespace of the
|
||||
* source entity.
|
||||
*/
|
||||
final public function __construct(
|
||||
public readonly string $fieldName,
|
||||
public string $sourceEntity,
|
||||
public readonly string $targetEntity,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $mappingArray
|
||||
* @phpstan-param array{
|
||||
* fieldName: string,
|
||||
* sourceEntity: class-string,
|
||||
* targetEntity: class-string,
|
||||
* cascade?: list<'persist'|'remove'|'detach'|'refresh'|'all'>,
|
||||
* fetch?: ClassMetadata::FETCH_*|null,
|
||||
* inherited?: class-string|null,
|
||||
* declared?: class-string|null,
|
||||
* cache?: array<mixed>|null,
|
||||
* id?: bool|null,
|
||||
* isOnDeleteCascade?: bool|null,
|
||||
* originalClass?: class-string|null,
|
||||
* originalField?: string|null,
|
||||
* orphanRemoval?: bool,
|
||||
* unique?: bool|null,
|
||||
* joinTable?: mixed[]|null,
|
||||
* type?: int,
|
||||
* isOwningSide: bool,
|
||||
* } $mappingArray
|
||||
*/
|
||||
public static function fromMappingArray(array $mappingArray): static
|
||||
{
|
||||
unset($mappingArray['isOwningSide'], $mappingArray['type']);
|
||||
$mapping = new static(
|
||||
$mappingArray['fieldName'],
|
||||
$mappingArray['sourceEntity'],
|
||||
$mappingArray['targetEntity'],
|
||||
);
|
||||
unset($mappingArray['fieldName'], $mappingArray['sourceEntity'], $mappingArray['targetEntity']);
|
||||
|
||||
foreach ($mappingArray as $key => $value) {
|
||||
if ($key === 'joinTable') {
|
||||
assert($mapping instanceof ManyToManyAssociationMapping);
|
||||
|
||||
if ($value === [] || $value === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $mapping instanceof ManyToManyOwningSideMapping) {
|
||||
throw new MappingException(
|
||||
"Mapping error on field '" .
|
||||
$mapping->fieldName . "' in " . $mapping->sourceEntity .
|
||||
" : 'joinTable' can only be set on many-to-many owning side.",
|
||||
);
|
||||
}
|
||||
|
||||
$mapping->joinTable = JoinTableMapping::fromMappingArray($value);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property_exists($mapping, $key)) {
|
||||
$mapping->$key = $value;
|
||||
} else {
|
||||
throw new OutOfRangeException('Unknown property ' . $key . ' on class ' . static::class);
|
||||
}
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-assert-if-true OwningSideMapping $this
|
||||
* @phpstan-assert-if-false InverseSideMapping $this
|
||||
*/
|
||||
final public function isOwningSide(): bool
|
||||
{
|
||||
return $this instanceof OwningSideMapping;
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true ToOneAssociationMapping $this */
|
||||
final public function isToOne(): bool
|
||||
{
|
||||
return $this instanceof ToOneAssociationMapping;
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true ToManyAssociationMapping $this */
|
||||
final public function isToMany(): bool
|
||||
{
|
||||
return $this instanceof ToManyAssociationMapping;
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true OneToOneOwningSideMapping $this */
|
||||
final public function isOneToOneOwningSide(): bool
|
||||
{
|
||||
return $this->isOneToOne() && $this->isOwningSide();
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true OneToOneOwningSideMapping|ManyToOneAssociationMapping $this */
|
||||
final public function isToOneOwningSide(): bool
|
||||
{
|
||||
return $this->isToOne() && $this->isOwningSide();
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true ManyToManyOwningSideMapping $this */
|
||||
final public function isManyToManyOwningSide(): bool
|
||||
{
|
||||
return $this instanceof ManyToManyOwningSideMapping;
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true OneToOneAssociationMapping $this */
|
||||
final public function isOneToOne(): bool
|
||||
{
|
||||
return $this instanceof OneToOneAssociationMapping;
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true OneToManyAssociationMapping $this */
|
||||
final public function isOneToMany(): bool
|
||||
{
|
||||
return $this instanceof OneToManyAssociationMapping;
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true ManyToOneAssociationMapping $this */
|
||||
final public function isManyToOne(): bool
|
||||
{
|
||||
return $this instanceof ManyToOneAssociationMapping;
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true ManyToManyAssociationMapping $this */
|
||||
final public function isManyToMany(): bool
|
||||
{
|
||||
return $this instanceof ManyToManyAssociationMapping;
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true ToManyAssociationMapping $this */
|
||||
final public function isOrdered(): bool
|
||||
{
|
||||
return $this->isToMany() && $this->orderBy() !== [];
|
||||
}
|
||||
|
||||
/** @phpstan-assert-if-true ToManyAssociationMapping $this */
|
||||
public function isIndexed(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final public function type(): int
|
||||
{
|
||||
return match (true) {
|
||||
$this instanceof OneToOneAssociationMapping => ClassMetadata::ONE_TO_ONE,
|
||||
$this instanceof OneToManyAssociationMapping => ClassMetadata::ONE_TO_MANY,
|
||||
$this instanceof ManyToOneAssociationMapping => ClassMetadata::MANY_TO_ONE,
|
||||
$this instanceof ManyToManyAssociationMapping => ClassMetadata::MANY_TO_MANY,
|
||||
default => throw new Exception('Cannot determine type for ' . static::class),
|
||||
};
|
||||
}
|
||||
|
||||
/** @param string $offset */
|
||||
public function offsetExists(mixed $offset): bool
|
||||
{
|
||||
return isset($this->$offset) || in_array($offset, ['isOwningSide', 'type'], true);
|
||||
}
|
||||
|
||||
final public function offsetGet(mixed $offset): mixed
|
||||
{
|
||||
return match ($offset) {
|
||||
'isOwningSide' => $this->isOwningSide(),
|
||||
'type' => $this->type(),
|
||||
'isCascadeRemove' => $this->isCascadeRemove(),
|
||||
'isCascadePersist' => $this->isCascadePersist(),
|
||||
'isCascadeRefresh' => $this->isCascadeRefresh(),
|
||||
'isCascadeDetach' => $this->isCascadeDetach(),
|
||||
default => property_exists($this, $offset) ? $this->$offset : throw new OutOfRangeException(sprintf(
|
||||
'Unknown property "%s" on class %s',
|
||||
$offset,
|
||||
static::class,
|
||||
)),
|
||||
};
|
||||
}
|
||||
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
assert($offset !== null);
|
||||
if (! property_exists($this, $offset)) {
|
||||
throw new OutOfRangeException(sprintf(
|
||||
'Unknown property "%s" on class %s',
|
||||
$offset,
|
||||
static::class,
|
||||
));
|
||||
}
|
||||
|
||||
if ($offset === 'joinTable') {
|
||||
$value = JoinTableMapping::fromMappingArray($value);
|
||||
}
|
||||
|
||||
$this->$offset = $value;
|
||||
}
|
||||
|
||||
/** @param string $offset */
|
||||
public function offsetUnset(mixed $offset): void
|
||||
{
|
||||
if (! property_exists($this, $offset)) {
|
||||
throw new OutOfRangeException(sprintf(
|
||||
'Unknown property "%s" on class %s',
|
||||
$offset,
|
||||
static::class,
|
||||
));
|
||||
}
|
||||
|
||||
$this->$offset = null;
|
||||
}
|
||||
|
||||
final public function isCascadeRemove(): bool
|
||||
{
|
||||
return in_array('remove', $this->cascade, true);
|
||||
}
|
||||
|
||||
final public function isCascadePersist(): bool
|
||||
{
|
||||
return in_array('persist', $this->cascade, true);
|
||||
}
|
||||
|
||||
final public function isCascadeRefresh(): bool
|
||||
{
|
||||
return in_array('refresh', $this->cascade, true);
|
||||
}
|
||||
|
||||
final public function isCascadeDetach(): bool
|
||||
{
|
||||
return in_array('detach', $this->cascade, true);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function toArray(): array
|
||||
{
|
||||
$array = (array) $this;
|
||||
|
||||
$array['isOwningSide'] = $this->isOwningSide();
|
||||
$array['type'] = $this->type();
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function __sleep(): array
|
||||
{
|
||||
$serialized = ['fieldName', 'sourceEntity', 'targetEntity'];
|
||||
|
||||
if (count($this->cascade) > 0) {
|
||||
$serialized[] = 'cascade';
|
||||
}
|
||||
|
||||
foreach (
|
||||
[
|
||||
'fetch',
|
||||
'inherited',
|
||||
'declared',
|
||||
'cache',
|
||||
'originalClass',
|
||||
'originalField',
|
||||
] as $stringOrArrayProperty
|
||||
) {
|
||||
if ($this->$stringOrArrayProperty !== null) {
|
||||
$serialized[] = $stringOrArrayProperty;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['id', 'orphanRemoval', 'isOnDeleteCascade', 'unique'] as $boolProperty) {
|
||||
if ($this->$boolProperty) {
|
||||
$serialized[] = $boolProperty;
|
||||
}
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
51
backend/vendor/doctrine/orm/src/Mapping/AssociationOverride.php
vendored
Normal file
51
backend/vendor/doctrine/orm/src/Mapping/AssociationOverride.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/** This attribute is used to override association mapping of property for an entity relationship. */
|
||||
final class AssociationOverride implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* The join column that is being mapped to the persistent attribute.
|
||||
*
|
||||
* @var array<JoinColumn>|null
|
||||
*/
|
||||
public readonly array|null $joinColumns;
|
||||
|
||||
/**
|
||||
* The join column that is being mapped to the persistent attribute.
|
||||
*
|
||||
* @var array<JoinColumn>|null
|
||||
*/
|
||||
public readonly array|null $inverseJoinColumns;
|
||||
|
||||
/**
|
||||
* @param string $name The name of the relationship property whose mapping is being overridden.
|
||||
* @param JoinColumn|array<JoinColumn> $joinColumns
|
||||
* @param JoinColumn|array<JoinColumn> $inverseJoinColumns
|
||||
* @param JoinTable|null $joinTable The join table that maps the relationship.
|
||||
* @param string|null $inversedBy The name of the association-field on the inverse-side.
|
||||
* @phpstan-param 'LAZY'|'EAGER'|'EXTRA_LAZY'|null $fetch
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $name,
|
||||
array|JoinColumn|null $joinColumns = null,
|
||||
array|JoinColumn|null $inverseJoinColumns = null,
|
||||
public readonly JoinTable|null $joinTable = null,
|
||||
public readonly string|null $inversedBy = null,
|
||||
public readonly string|null $fetch = null,
|
||||
) {
|
||||
if ($joinColumns instanceof JoinColumn) {
|
||||
$joinColumns = [$joinColumns];
|
||||
}
|
||||
|
||||
if ($inverseJoinColumns instanceof JoinColumn) {
|
||||
$inverseJoinColumns = [$inverseJoinColumns];
|
||||
}
|
||||
|
||||
$this->joinColumns = $joinColumns;
|
||||
$this->inverseJoinColumns = $inverseJoinColumns;
|
||||
}
|
||||
}
|
||||
38
backend/vendor/doctrine/orm/src/Mapping/AssociationOverrides.php
vendored
Normal file
38
backend/vendor/doctrine/orm/src/Mapping/AssociationOverrides.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
use function array_values;
|
||||
use function is_array;
|
||||
|
||||
/** This attribute is used to override association mappings of relationship properties. */
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class AssociationOverrides implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* Mapping overrides of relationship properties.
|
||||
*
|
||||
* @var list<AssociationOverride>
|
||||
*/
|
||||
public readonly array $overrides;
|
||||
|
||||
/** @param array<AssociationOverride>|AssociationOverride $overrides */
|
||||
public function __construct(array|AssociationOverride $overrides)
|
||||
{
|
||||
if (! is_array($overrides)) {
|
||||
$overrides = [$overrides];
|
||||
}
|
||||
|
||||
foreach ($overrides as $override) {
|
||||
if (! ($override instanceof AssociationOverride)) {
|
||||
throw MappingException::invalidOverrideType('AssociationOverride', $override);
|
||||
}
|
||||
}
|
||||
|
||||
$this->overrides = array_values($overrides);
|
||||
}
|
||||
}
|
||||
15
backend/vendor/doctrine/orm/src/Mapping/AttributeOverride.php
vendored
Normal file
15
backend/vendor/doctrine/orm/src/Mapping/AttributeOverride.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/** This attribute is used to override the mapping of a entity property. */
|
||||
final class AttributeOverride implements MappingAttribute
|
||||
{
|
||||
public function __construct(
|
||||
public string $name,
|
||||
public Column $column,
|
||||
) {
|
||||
}
|
||||
}
|
||||
38
backend/vendor/doctrine/orm/src/Mapping/AttributeOverrides.php
vendored
Normal file
38
backend/vendor/doctrine/orm/src/Mapping/AttributeOverrides.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
use function array_values;
|
||||
use function is_array;
|
||||
|
||||
/** This attribute is used to override the mapping of a entity property. */
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class AttributeOverrides implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* One or more field or property mapping overrides.
|
||||
*
|
||||
* @var list<AttributeOverride>
|
||||
*/
|
||||
public readonly array $overrides;
|
||||
|
||||
/** @param array<AttributeOverride>|AttributeOverride $overrides */
|
||||
public function __construct(array|AttributeOverride $overrides)
|
||||
{
|
||||
if (! is_array($overrides)) {
|
||||
$overrides = [$overrides];
|
||||
}
|
||||
|
||||
foreach ($overrides as $override) {
|
||||
if (! ($override instanceof AttributeOverride)) {
|
||||
throw MappingException::invalidOverrideType('AttributeOverride', $override);
|
||||
}
|
||||
}
|
||||
|
||||
$this->overrides = array_values($overrides);
|
||||
}
|
||||
}
|
||||
178
backend/vendor/doctrine/orm/src/Mapping/Builder/AssociationBuilder.php
vendored
Normal file
178
backend/vendor/doctrine/orm/src/Mapping/Builder/AssociationBuilder.php
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class AssociationBuilder
|
||||
{
|
||||
/** @var mixed[]|null */
|
||||
protected array|null $joinColumns = null;
|
||||
|
||||
/** @param mixed[] $mapping */
|
||||
public function __construct(
|
||||
protected readonly ClassMetadataBuilder $builder,
|
||||
protected array $mapping,
|
||||
protected readonly int $type,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function mappedBy(string $fieldName): static
|
||||
{
|
||||
$this->mapping['mappedBy'] = $fieldName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function inversedBy(string $fieldName): static
|
||||
{
|
||||
$this->mapping['inversedBy'] = $fieldName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function cascadeAll(): static
|
||||
{
|
||||
$this->mapping['cascade'] = ['ALL'];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function cascadePersist(): static
|
||||
{
|
||||
$this->mapping['cascade'][] = 'persist';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function cascadeRemove(): static
|
||||
{
|
||||
$this->mapping['cascade'][] = 'remove';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function cascadeDetach(): static
|
||||
{
|
||||
$this->mapping['cascade'][] = 'detach';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function cascadeRefresh(): static
|
||||
{
|
||||
$this->mapping['cascade'][] = 'refresh';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function fetchExtraLazy(): static
|
||||
{
|
||||
$this->mapping['fetch'] = ClassMetadata::FETCH_EXTRA_LAZY;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function fetchEager(): static
|
||||
{
|
||||
$this->mapping['fetch'] = ClassMetadata::FETCH_EAGER;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function fetchLazy(): static
|
||||
{
|
||||
$this->mapping['fetch'] = ClassMetadata::FETCH_LAZY;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Join Columns.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addJoinColumn(
|
||||
string $columnName,
|
||||
string $referencedColumnName,
|
||||
bool $nullable = true,
|
||||
bool $unique = false,
|
||||
string|null $onDelete = null,
|
||||
string|null $columnDef = null,
|
||||
): static {
|
||||
if ($this->mapping['id'] ?? false) {
|
||||
$nullable = null;
|
||||
}
|
||||
|
||||
$this->joinColumns[] = [
|
||||
'name' => $columnName,
|
||||
'referencedColumnName' => $referencedColumnName,
|
||||
'nullable' => $nullable,
|
||||
'unique' => $unique,
|
||||
'onDelete' => $onDelete,
|
||||
'columnDefinition' => $columnDef,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets field as primary key.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function makePrimaryKey(): static
|
||||
{
|
||||
$this->mapping['id'] = true;
|
||||
foreach ($this->joinColumns ?? [] as $i => $joinColumn) {
|
||||
$this->joinColumns[$i]['nullable'] = null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes orphan entities when detached from their parent.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function orphanRemoval(): static
|
||||
{
|
||||
$this->mapping['orphanRemoval'] = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @throws InvalidArgumentException */
|
||||
public function build(): ClassMetadataBuilder
|
||||
{
|
||||
$mapping = $this->mapping;
|
||||
if ($this->joinColumns) {
|
||||
$mapping['joinColumns'] = $this->joinColumns;
|
||||
}
|
||||
|
||||
$cm = $this->builder->getClassMetadata();
|
||||
if ($this->type === ClassMetadata::MANY_TO_ONE) {
|
||||
$cm->mapManyToOne($mapping);
|
||||
} elseif ($this->type === ClassMetadata::ONE_TO_ONE) {
|
||||
$cm->mapOneToOne($mapping);
|
||||
} else {
|
||||
throw new InvalidArgumentException('Type should be a ToOne Association here');
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
426
backend/vendor/doctrine/orm/src/Mapping/Builder/ClassMetadataBuilder.php
vendored
Normal file
426
backend/vendor/doctrine/orm/src/Mapping/Builder/ClassMetadataBuilder.php
vendored
Normal file
@@ -0,0 +1,426 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
use BackedEnum;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
|
||||
/**
|
||||
* Builder Object for ClassMetadata
|
||||
*
|
||||
* @link www.doctrine-project.com
|
||||
*/
|
||||
class ClassMetadataBuilder
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ClassMetadata $cm,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getClassMetadata(): ClassMetadata
|
||||
{
|
||||
return $this->cm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the class as mapped superclass.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMappedSuperClass(): static
|
||||
{
|
||||
$this->cm->isMappedSuperclass = true;
|
||||
$this->cm->isEmbeddedClass = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the class as embeddable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setEmbeddable(): static
|
||||
{
|
||||
$this->cm->isEmbeddedClass = true;
|
||||
$this->cm->isMappedSuperclass = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds and embedded class
|
||||
*
|
||||
* @param class-string $class
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addEmbedded(string $fieldName, string $class, string|false|null $columnPrefix = null): static
|
||||
{
|
||||
$this->cm->mapEmbedded(
|
||||
[
|
||||
'fieldName' => $fieldName,
|
||||
'class' => $class,
|
||||
'columnPrefix' => $columnPrefix,
|
||||
],
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets custom Repository class name.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustomRepositoryClass(string $repositoryClassName): static
|
||||
{
|
||||
$this->cm->setCustomRepositoryClass($repositoryClassName);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks class read only.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setReadOnly(): static
|
||||
{
|
||||
$this->cm->markReadOnly();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table name.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTable(string $name): static
|
||||
{
|
||||
$this->cm->setPrimaryTable(['name' => $name]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Index.
|
||||
*
|
||||
* @phpstan-param list<string> $columns
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addIndex(array $columns, string $name): static
|
||||
{
|
||||
if (! isset($this->cm->table['indexes'])) {
|
||||
$this->cm->table['indexes'] = [];
|
||||
}
|
||||
|
||||
$this->cm->table['indexes'][$name] = ['columns' => $columns];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Unique Constraint.
|
||||
*
|
||||
* @phpstan-param list<string> $columns
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addUniqueConstraint(array $columns, string $name): static
|
||||
{
|
||||
if (! isset($this->cm->table['uniqueConstraints'])) {
|
||||
$this->cm->table['uniqueConstraints'] = [];
|
||||
}
|
||||
|
||||
$this->cm->table['uniqueConstraints'][$name] = ['columns' => $columns];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets class as root of a joined table inheritance hierarchy.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setJoinedTableInheritance(): static
|
||||
{
|
||||
$this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_JOINED);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets class as root of a single table inheritance hierarchy.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSingleTableInheritance(): static
|
||||
{
|
||||
$this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the discriminator column details.
|
||||
*
|
||||
* @param class-string<BackedEnum>|null $enumType
|
||||
* @param array<string, mixed> $options
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDiscriminatorColumn(
|
||||
string $name,
|
||||
string $type = 'string',
|
||||
int $length = 255,
|
||||
string|null $columnDefinition = null,
|
||||
string|null $enumType = null,
|
||||
array $options = [],
|
||||
): static {
|
||||
$this->cm->setDiscriminatorColumn(
|
||||
[
|
||||
'name' => $name,
|
||||
'type' => $type,
|
||||
'length' => $length,
|
||||
'columnDefinition' => $columnDefinition,
|
||||
'enumType' => $enumType,
|
||||
'options' => $options,
|
||||
],
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a subclass to this inheritance hierarchy.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addDiscriminatorMapClass(string $name, string $class): static
|
||||
{
|
||||
$this->cm->addDiscriminatorMapClass($name, $class);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets deferred explicit change tracking policy.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setChangeTrackingPolicyDeferredExplicit(): static
|
||||
{
|
||||
$this->cm->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_DEFERRED_EXPLICIT);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds lifecycle event.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addLifecycleEvent(string $methodName, string $event): static
|
||||
{
|
||||
$this->cm->addLifecycleCallback($methodName, $event);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Field.
|
||||
*
|
||||
* @phpstan-param array<string, mixed> $mapping
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addField(string $name, string $type, array $mapping = []): static
|
||||
{
|
||||
$mapping['fieldName'] = $name;
|
||||
$mapping['type'] = $type;
|
||||
|
||||
$this->cm->mapField($mapping);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a field builder.
|
||||
*/
|
||||
public function createField(string $name, string $type): FieldBuilder
|
||||
{
|
||||
return new FieldBuilder(
|
||||
$this,
|
||||
[
|
||||
'fieldName' => $name,
|
||||
'type' => $type,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an embedded builder.
|
||||
*/
|
||||
public function createEmbedded(string $fieldName, string $class): EmbeddedBuilder
|
||||
{
|
||||
return new EmbeddedBuilder(
|
||||
$this,
|
||||
[
|
||||
'fieldName' => $fieldName,
|
||||
'class' => $class,
|
||||
'columnPrefix' => null,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a simple many to one association, optionally with the inversed by field.
|
||||
*/
|
||||
public function addManyToOne(
|
||||
string $name,
|
||||
string $targetEntity,
|
||||
string|null $inversedBy = null,
|
||||
): ClassMetadataBuilder {
|
||||
$builder = $this->createManyToOne($name, $targetEntity);
|
||||
|
||||
if ($inversedBy !== null) {
|
||||
$builder->inversedBy($inversedBy);
|
||||
}
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ManyToOne Association Builder.
|
||||
*
|
||||
* Note: This method does not add the association, you have to call build() on the AssociationBuilder.
|
||||
*/
|
||||
public function createManyToOne(string $name, string $targetEntity): AssociationBuilder
|
||||
{
|
||||
return new AssociationBuilder(
|
||||
$this,
|
||||
[
|
||||
'fieldName' => $name,
|
||||
'targetEntity' => $targetEntity,
|
||||
],
|
||||
ClassMetadata::MANY_TO_ONE,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a OneToOne Association Builder.
|
||||
*/
|
||||
public function createOneToOne(string $name, string $targetEntity): AssociationBuilder
|
||||
{
|
||||
return new AssociationBuilder(
|
||||
$this,
|
||||
[
|
||||
'fieldName' => $name,
|
||||
'targetEntity' => $targetEntity,
|
||||
],
|
||||
ClassMetadata::ONE_TO_ONE,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds simple inverse one-to-one association.
|
||||
*/
|
||||
public function addInverseOneToOne(string $name, string $targetEntity, string $mappedBy): ClassMetadataBuilder
|
||||
{
|
||||
$builder = $this->createOneToOne($name, $targetEntity);
|
||||
$builder->mappedBy($mappedBy);
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds simple owning one-to-one association.
|
||||
*/
|
||||
public function addOwningOneToOne(
|
||||
string $name,
|
||||
string $targetEntity,
|
||||
string|null $inversedBy = null,
|
||||
): ClassMetadataBuilder {
|
||||
$builder = $this->createOneToOne($name, $targetEntity);
|
||||
|
||||
if ($inversedBy !== null) {
|
||||
$builder->inversedBy($inversedBy);
|
||||
}
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ManyToMany Association Builder.
|
||||
*/
|
||||
public function createManyToMany(string $name, string $targetEntity): ManyToManyAssociationBuilder
|
||||
{
|
||||
return new ManyToManyAssociationBuilder(
|
||||
$this,
|
||||
[
|
||||
'fieldName' => $name,
|
||||
'targetEntity' => $targetEntity,
|
||||
],
|
||||
ClassMetadata::MANY_TO_MANY,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a simple owning many to many association.
|
||||
*/
|
||||
public function addOwningManyToMany(
|
||||
string $name,
|
||||
string $targetEntity,
|
||||
string|null $inversedBy = null,
|
||||
): ClassMetadataBuilder {
|
||||
$builder = $this->createManyToMany($name, $targetEntity);
|
||||
|
||||
if ($inversedBy !== null) {
|
||||
$builder->inversedBy($inversedBy);
|
||||
}
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a simple inverse many to many association.
|
||||
*/
|
||||
public function addInverseManyToMany(string $name, string $targetEntity, string $mappedBy): ClassMetadataBuilder
|
||||
{
|
||||
$builder = $this->createManyToMany($name, $targetEntity);
|
||||
$builder->mappedBy($mappedBy);
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a one to many association builder.
|
||||
*/
|
||||
public function createOneToMany(string $name, string $targetEntity): OneToManyAssociationBuilder
|
||||
{
|
||||
return new OneToManyAssociationBuilder(
|
||||
$this,
|
||||
[
|
||||
'fieldName' => $name,
|
||||
'targetEntity' => $targetEntity,
|
||||
],
|
||||
ClassMetadata::ONE_TO_MANY,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds simple OneToMany association.
|
||||
*/
|
||||
public function addOneToMany(string $name, string $targetEntity, string $mappedBy): ClassMetadataBuilder
|
||||
{
|
||||
$builder = $this->createOneToMany($name, $targetEntity);
|
||||
$builder->mappedBy($mappedBy);
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
}
|
||||
46
backend/vendor/doctrine/orm/src/Mapping/Builder/EmbeddedBuilder.php
vendored
Normal file
46
backend/vendor/doctrine/orm/src/Mapping/Builder/EmbeddedBuilder.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
/**
|
||||
* Embedded Builder
|
||||
*
|
||||
* @link www.doctrine-project.com
|
||||
*/
|
||||
class EmbeddedBuilder
|
||||
{
|
||||
/** @param mixed[] $mapping */
|
||||
public function __construct(
|
||||
private readonly ClassMetadataBuilder $builder,
|
||||
private array $mapping,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the column prefix for all of the embedded columns.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnPrefix(string $columnPrefix): static
|
||||
{
|
||||
$this->mapping['columnPrefix'] = $columnPrefix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes this embeddable and attach it to the ClassMetadata.
|
||||
*
|
||||
* Without this call an EmbeddedBuilder has no effect on the ClassMetadata.
|
||||
*/
|
||||
public function build(): ClassMetadataBuilder
|
||||
{
|
||||
$cm = $this->builder->getClassMetadata();
|
||||
|
||||
$cm->mapEmbedded($this->mapping);
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
55
backend/vendor/doctrine/orm/src/Mapping/Builder/EntityListenerBuilder.php
vendored
Normal file
55
backend/vendor/doctrine/orm/src/Mapping/Builder/EntityListenerBuilder.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
use Doctrine\ORM\Events;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
|
||||
use function class_exists;
|
||||
use function get_class_methods;
|
||||
|
||||
/**
|
||||
* Builder for entity listeners.
|
||||
*/
|
||||
class EntityListenerBuilder
|
||||
{
|
||||
/** Hash-map to handle event names. */
|
||||
private const EVENTS = [
|
||||
Events::preRemove => true,
|
||||
Events::postRemove => true,
|
||||
Events::prePersist => true,
|
||||
Events::postPersist => true,
|
||||
Events::preUpdate => true,
|
||||
Events::postUpdate => true,
|
||||
Events::postLoad => true,
|
||||
Events::preFlush => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Lookup the entity class to find methods that match to event lifecycle names
|
||||
*
|
||||
* @param ClassMetadata $metadata The entity metadata.
|
||||
* @param string $className The listener class name.
|
||||
*
|
||||
* @throws MappingException When the listener class not found.
|
||||
*/
|
||||
public static function bindEntityListener(ClassMetadata $metadata, string $className): void
|
||||
{
|
||||
$class = $metadata->fullyQualifiedClassName($className);
|
||||
|
||||
if (! class_exists($class)) {
|
||||
throw MappingException::entityListenerClassNotFound($class, $className);
|
||||
}
|
||||
|
||||
foreach (get_class_methods($class) as $method) {
|
||||
if (! isset(self::EVENTS[$method])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$metadata->addEntityListener($method, $class, $method);
|
||||
}
|
||||
}
|
||||
}
|
||||
255
backend/vendor/doctrine/orm/src/Mapping/Builder/FieldBuilder.php
vendored
Normal file
255
backend/vendor/doctrine/orm/src/Mapping/Builder/FieldBuilder.php
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
use function constant;
|
||||
|
||||
/**
|
||||
* Field Builder
|
||||
*
|
||||
* @link www.doctrine-project.com
|
||||
*/
|
||||
class FieldBuilder
|
||||
{
|
||||
private bool $version = false;
|
||||
private string|null $generatedValue = null;
|
||||
|
||||
/** @var mixed[]|null */
|
||||
private array|null $sequenceDef = null;
|
||||
|
||||
private string|null $customIdGenerator = null;
|
||||
|
||||
/** @param mixed[] $mapping */
|
||||
public function __construct(
|
||||
private readonly ClassMetadataBuilder $builder,
|
||||
private array $mapping,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets length.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function length(int $length): static
|
||||
{
|
||||
$this->mapping['length'] = $length;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets nullable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function nullable(bool $flag = true): static
|
||||
{
|
||||
$this->mapping['nullable'] = $flag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Unique.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function unique(bool $flag = true): static
|
||||
{
|
||||
$this->mapping['unique'] = $flag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets indexed.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function index(bool $flag = true): static
|
||||
{
|
||||
$this->mapping['index'] = $flag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets column name.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function columnName(string $name): static
|
||||
{
|
||||
$this->mapping['columnName'] = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Precision.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function precision(int $p): static
|
||||
{
|
||||
$this->mapping['precision'] = $p;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets insertable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function insertable(bool $flag = true): self
|
||||
{
|
||||
if (! $flag) {
|
||||
$this->mapping['notInsertable'] = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets updatable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function updatable(bool $flag = true): self
|
||||
{
|
||||
if (! $flag) {
|
||||
$this->mapping['notUpdatable'] = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets scale.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function scale(int $s): static
|
||||
{
|
||||
$this->mapping['scale'] = $s;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets field as primary key.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function makePrimaryKey(): static
|
||||
{
|
||||
$this->mapping['id'] = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an option.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function option(string $name, mixed $value): static
|
||||
{
|
||||
$this->mapping['options'][$name] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function generatedValue(string $strategy = 'AUTO'): static
|
||||
{
|
||||
$this->generatedValue = $strategy;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets field versioned.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function isVersionField(): static
|
||||
{
|
||||
$this->version = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Sequence Generator.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSequenceGenerator(string $sequenceName, int $allocationSize = 1, int $initialValue = 1): static
|
||||
{
|
||||
$this->sequenceDef = [
|
||||
'sequenceName' => $sequenceName,
|
||||
'allocationSize' => $allocationSize,
|
||||
'initialValue' => $initialValue,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets column definition.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function columnDefinition(string $def): static
|
||||
{
|
||||
$this->mapping['columnDefinition'] = $def;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the FQCN of the custom ID generator.
|
||||
* This class must extend \Doctrine\ORM\Id\AbstractIdGenerator.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustomIdGenerator(string $customIdGenerator): static
|
||||
{
|
||||
$this->customIdGenerator = $customIdGenerator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes this field and attach it to the ClassMetadata.
|
||||
*
|
||||
* Without this call a FieldBuilder has no effect on the ClassMetadata.
|
||||
*/
|
||||
public function build(): ClassMetadataBuilder
|
||||
{
|
||||
$cm = $this->builder->getClassMetadata();
|
||||
if ($this->generatedValue) {
|
||||
$cm->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $this->generatedValue));
|
||||
}
|
||||
|
||||
if ($this->version) {
|
||||
$cm->setVersionMapping($this->mapping);
|
||||
}
|
||||
|
||||
$cm->mapField($this->mapping);
|
||||
if ($this->sequenceDef) {
|
||||
$cm->setSequenceGeneratorDefinition($this->sequenceDef);
|
||||
}
|
||||
|
||||
if ($this->customIdGenerator) {
|
||||
$cm->setCustomGeneratorDefinition(['class' => $this->customIdGenerator]);
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
96
backend/vendor/doctrine/orm/src/Mapping/Builder/ManyToManyAssociationBuilder.php
vendored
Normal file
96
backend/vendor/doctrine/orm/src/Mapping/Builder/ManyToManyAssociationBuilder.php
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
/**
|
||||
* ManyToMany Association Builder
|
||||
*
|
||||
* @link www.doctrine-project.com
|
||||
*/
|
||||
class ManyToManyAssociationBuilder extends OneToManyAssociationBuilder
|
||||
{
|
||||
private string|null $joinTableName = null;
|
||||
|
||||
/** @var mixed[] */
|
||||
private array $inverseJoinColumns = [];
|
||||
|
||||
/** @return $this */
|
||||
public function setJoinTable(string $name): static
|
||||
{
|
||||
$this->joinTableName = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Join Columns.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addJoinColumn(
|
||||
string $columnName,
|
||||
string $referencedColumnName,
|
||||
bool $nullable = true,
|
||||
bool $unique = false,
|
||||
string|null $onDelete = null,
|
||||
string|null $columnDef = null,
|
||||
): static {
|
||||
$this->joinColumns[] = [
|
||||
'name' => $columnName,
|
||||
'referencedColumnName' => $referencedColumnName,
|
||||
'unique' => $unique,
|
||||
'onDelete' => $onDelete,
|
||||
'columnDefinition' => $columnDef,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Inverse Join Columns.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addInverseJoinColumn(
|
||||
string $columnName,
|
||||
string $referencedColumnName,
|
||||
bool $nullable = true,
|
||||
bool $unique = false,
|
||||
string|null $onDelete = null,
|
||||
string|null $columnDef = null,
|
||||
): static {
|
||||
$this->inverseJoinColumns[] = [
|
||||
'name' => $columnName,
|
||||
'referencedColumnName' => $referencedColumnName,
|
||||
'unique' => $unique,
|
||||
'onDelete' => $onDelete,
|
||||
'columnDefinition' => $columnDef,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function build(): ClassMetadataBuilder
|
||||
{
|
||||
$mapping = $this->mapping;
|
||||
$mapping['joinTable'] = [];
|
||||
if ($this->joinColumns) {
|
||||
$mapping['joinTable']['joinColumns'] = $this->joinColumns;
|
||||
}
|
||||
|
||||
if ($this->inverseJoinColumns) {
|
||||
$mapping['joinTable']['inverseJoinColumns'] = $this->inverseJoinColumns;
|
||||
}
|
||||
|
||||
if ($this->joinTableName) {
|
||||
$mapping['joinTable']['name'] = $this->joinTableName;
|
||||
}
|
||||
|
||||
$cm = $this->builder->getClassMetadata();
|
||||
$cm->mapManyToMany($mapping);
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
46
backend/vendor/doctrine/orm/src/Mapping/Builder/OneToManyAssociationBuilder.php
vendored
Normal file
46
backend/vendor/doctrine/orm/src/Mapping/Builder/OneToManyAssociationBuilder.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
/**
|
||||
* OneToMany Association Builder
|
||||
*
|
||||
* @link www.doctrine-project.com
|
||||
*/
|
||||
class OneToManyAssociationBuilder extends AssociationBuilder
|
||||
{
|
||||
/**
|
||||
* @phpstan-param array<string, string> $fieldNames
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOrderBy(array $fieldNames): static
|
||||
{
|
||||
$this->mapping['orderBy'] = $fieldNames;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function setIndexBy(string $fieldName): static
|
||||
{
|
||||
$this->mapping['indexBy'] = $fieldName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function build(): ClassMetadataBuilder
|
||||
{
|
||||
$mapping = $this->mapping;
|
||||
if ($this->joinColumns) {
|
||||
$mapping['joinColumns'] = $this->joinColumns;
|
||||
}
|
||||
|
||||
$cm = $this->builder->getClassMetadata();
|
||||
$cm->mapOneToMany($mapping);
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
19
backend/vendor/doctrine/orm/src/Mapping/Cache.php
vendored
Normal file
19
backend/vendor/doctrine/orm/src/Mapping/Cache.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
/** Caching to an entity or a collection. */
|
||||
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_PROPERTY)]
|
||||
final class Cache implements MappingAttribute
|
||||
{
|
||||
/** @phpstan-param 'READ_ONLY'|'NONSTRICT_READ_WRITE'|'READ_WRITE' $usage */
|
||||
public function __construct(
|
||||
public readonly string $usage = 'READ_ONLY',
|
||||
public readonly string|null $region = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
35
backend/vendor/doctrine/orm/src/Mapping/ChainTypedFieldMapper.php
vendored
Normal file
35
backend/vendor/doctrine/orm/src/Mapping/ChainTypedFieldMapper.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\ORM\Internal\NoUnknownNamedArguments;
|
||||
use ReflectionProperty;
|
||||
|
||||
final class ChainTypedFieldMapper implements TypedFieldMapper
|
||||
{
|
||||
use NoUnknownNamedArguments;
|
||||
|
||||
/** @var list<TypedFieldMapper> $typedFieldMappers */
|
||||
private readonly array $typedFieldMappers;
|
||||
|
||||
public function __construct(TypedFieldMapper ...$typedFieldMappers)
|
||||
{
|
||||
self::validateVariadicParameter($typedFieldMappers);
|
||||
|
||||
$this->typedFieldMappers = $typedFieldMappers;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function validateAndComplete(array $mapping, ReflectionProperty $field): array
|
||||
{
|
||||
foreach ($this->typedFieldMappers as $typedFieldMapper) {
|
||||
$mapping = $typedFieldMapper->validateAndComplete($mapping, $field);
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Mapping/ChangeTrackingPolicy.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Mapping/ChangeTrackingPolicy.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class ChangeTrackingPolicy implements MappingAttribute
|
||||
{
|
||||
/** @phpstan-param 'DEFERRED_IMPLICIT'|'DEFERRED_EXPLICIT' $value */
|
||||
public function __construct(
|
||||
public readonly string $value,
|
||||
) {
|
||||
}
|
||||
}
|
||||
2725
backend/vendor/doctrine/orm/src/Mapping/ClassMetadata.php
vendored
Normal file
2725
backend/vendor/doctrine/orm/src/Mapping/ClassMetadata.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
745
backend/vendor/doctrine/orm/src/Mapping/ClassMetadataFactory.php
vendored
Normal file
745
backend/vendor/doctrine/orm/src/Mapping/ClassMetadataFactory.php
vendored
Normal file
@@ -0,0 +1,745 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\Common\EventManager;
|
||||
use Doctrine\DBAL\Platforms;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
|
||||
use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs;
|
||||
use Doctrine\ORM\Events;
|
||||
use Doctrine\ORM\Exception\ORMException;
|
||||
use Doctrine\ORM\Id\AssignedGenerator;
|
||||
use Doctrine\ORM\Id\BigIntegerIdentityGenerator;
|
||||
use Doctrine\ORM\Id\IdentityGenerator;
|
||||
use Doctrine\ORM\Id\SequenceGenerator;
|
||||
use Doctrine\ORM\Mapping\Exception\InvalidCustomGenerator;
|
||||
use Doctrine\ORM\Mapping\Exception\UnknownGeneratorType;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\Persistence\Mapping\AbstractClassMetadataFactory;
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata as ClassMetadataInterface;
|
||||
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
|
||||
use Doctrine\Persistence\Mapping\ReflectionService;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
|
||||
use function assert;
|
||||
use function class_exists;
|
||||
use function count;
|
||||
use function end;
|
||||
use function explode;
|
||||
use function in_array;
|
||||
use function is_a;
|
||||
use function is_subclass_of;
|
||||
use function method_exists;
|
||||
use function str_contains;
|
||||
use function strlen;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
|
||||
use const PHP_VERSION_ID;
|
||||
|
||||
/**
|
||||
* The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
|
||||
* metadata mapping information of a class which describes how a class should be mapped
|
||||
* to a relational database.
|
||||
*
|
||||
* @extends AbstractClassMetadataFactory<ClassMetadata>
|
||||
*/
|
||||
class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
{
|
||||
private EntityManagerInterface|null $em = null;
|
||||
private AbstractPlatform|null $targetPlatform = null;
|
||||
private MappingDriver|null $driver = null;
|
||||
private EventManager|null $evm = null;
|
||||
|
||||
/** @var mixed[] */
|
||||
private array $embeddablesActiveNesting = [];
|
||||
|
||||
private const NON_IDENTITY_DEFAULT_STRATEGY = [
|
||||
Platforms\OraclePlatform::class => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
|
||||
];
|
||||
|
||||
public function setEntityManager(EntityManagerInterface $em): void
|
||||
{
|
||||
if (! $em->getConfiguration()->isNativeLazyObjectsEnabled()) {
|
||||
parent::setProxyClassNameResolver(new DefaultProxyClassNameResolver());
|
||||
}
|
||||
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param A $maybeOwningSide
|
||||
*
|
||||
* @return (A is ManyToManyAssociationMapping ? ManyToManyOwningSideMapping : (
|
||||
* A is OneToOneAssociationMapping ? OneToOneOwningSideMapping : (
|
||||
* A is OneToManyAssociationMapping ? ManyToOneAssociationMapping : (
|
||||
* A is ManyToOneAssociationMapping ? ManyToOneAssociationMapping :
|
||||
* ManyToManyOwningSideMapping|OneToOneOwningSideMapping|ManyToOneAssociationMapping
|
||||
* ))))
|
||||
*
|
||||
* @template A of AssociationMapping
|
||||
*/
|
||||
final public function getOwningSide(AssociationMapping $maybeOwningSide): OwningSideMapping
|
||||
{
|
||||
if ($maybeOwningSide instanceof OwningSideMapping) {
|
||||
assert($maybeOwningSide instanceof ManyToManyOwningSideMapping ||
|
||||
$maybeOwningSide instanceof OneToOneOwningSideMapping ||
|
||||
$maybeOwningSide instanceof ManyToOneAssociationMapping);
|
||||
|
||||
return $maybeOwningSide;
|
||||
}
|
||||
|
||||
assert($maybeOwningSide instanceof InverseSideMapping);
|
||||
|
||||
$owningSide = $this->getMetadataFor($maybeOwningSide->targetEntity)
|
||||
->associationMappings[$maybeOwningSide->mappedBy];
|
||||
|
||||
assert($owningSide instanceof ManyToManyOwningSideMapping ||
|
||||
$owningSide instanceof OneToOneOwningSideMapping ||
|
||||
$owningSide instanceof ManyToOneAssociationMapping);
|
||||
|
||||
return $owningSide;
|
||||
}
|
||||
|
||||
protected function initialize(): void
|
||||
{
|
||||
$this->driver = $this->em->getConfiguration()->getMetadataDriverImpl();
|
||||
$this->evm = $this->em->getEventManager();
|
||||
$this->initialized = true;
|
||||
}
|
||||
|
||||
protected function onNotFoundMetadata(string $className): ClassMetadata|null
|
||||
{
|
||||
if (! $this->evm->hasListeners(Events::onClassMetadataNotFound)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$eventArgs = new OnClassMetadataNotFoundEventArgs($className, $this->em);
|
||||
|
||||
$this->evm->dispatchEvent(Events::onClassMetadataNotFound, $eventArgs);
|
||||
$classMetadata = $eventArgs->getFoundMetadata();
|
||||
assert($classMetadata instanceof ClassMetadata || $classMetadata === null);
|
||||
|
||||
return $classMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function doLoadMetadata(
|
||||
ClassMetadataInterface $class,
|
||||
ClassMetadataInterface|null $parent,
|
||||
bool $rootEntityFound,
|
||||
array $nonSuperclassParents,
|
||||
): void {
|
||||
if ($parent) {
|
||||
$class->setInheritanceType($parent->inheritanceType);
|
||||
$class->setDiscriminatorColumn($parent->discriminatorColumn === null ? null : clone $parent->discriminatorColumn);
|
||||
$class->setIdGeneratorType($parent->generatorType);
|
||||
$this->addInheritedFields($class, $parent);
|
||||
$this->addInheritedRelations($class, $parent);
|
||||
$this->addInheritedEmbeddedClasses($class, $parent);
|
||||
$class->setIdentifier($parent->identifier);
|
||||
$class->setVersioned($parent->isVersioned);
|
||||
$class->setVersionField($parent->versionField);
|
||||
$class->setDiscriminatorMap($parent->discriminatorMap);
|
||||
$class->addSubClasses($parent->subClasses);
|
||||
$class->setLifecycleCallbacks($parent->lifecycleCallbacks);
|
||||
$class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
|
||||
|
||||
if (! empty($parent->customGeneratorDefinition)) {
|
||||
$class->setCustomGeneratorDefinition($parent->customGeneratorDefinition);
|
||||
}
|
||||
|
||||
if ($parent->isMappedSuperclass) {
|
||||
$class->setCustomRepositoryClass($parent->customRepositoryClassName);
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke driver
|
||||
try {
|
||||
$this->driver->loadMetadataForClass($class->getName(), $class);
|
||||
} catch (ReflectionException $e) {
|
||||
throw MappingException::reflectionFailure($class->getName(), $e);
|
||||
}
|
||||
|
||||
// If this class has a parent the id generator strategy is inherited.
|
||||
// However this is only true if the hierarchy of parents contains the root entity,
|
||||
// if it consists of mapped superclasses these don't necessarily include the id field.
|
||||
if ($parent && $rootEntityFound) {
|
||||
$this->inheritIdGeneratorMapping($class, $parent);
|
||||
} else {
|
||||
$this->completeIdGeneratorMapping($class);
|
||||
}
|
||||
|
||||
if (! $class->isMappedSuperclass) {
|
||||
if ($rootEntityFound && $class->isInheritanceTypeNone()) {
|
||||
throw MappingException::missingInheritanceTypeDeclaration(end($nonSuperclassParents), $class->name);
|
||||
}
|
||||
|
||||
foreach ($class->embeddedClasses as $property => $embeddableClass) {
|
||||
if (isset($embeddableClass->inherited)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($this->embeddablesActiveNesting[$embeddableClass->class])) {
|
||||
throw MappingException::infiniteEmbeddableNesting($class->name, $property);
|
||||
}
|
||||
|
||||
$this->embeddablesActiveNesting[$class->name] = true;
|
||||
|
||||
$embeddableMetadata = $this->getMetadataFor($embeddableClass->class);
|
||||
|
||||
if ($embeddableMetadata->isEmbeddedClass) {
|
||||
$this->addNestedEmbeddedClasses($embeddableMetadata, $class, $property);
|
||||
}
|
||||
|
||||
$identifier = $embeddableMetadata->getIdentifier();
|
||||
|
||||
if (! empty($identifier)) {
|
||||
$this->inheritIdGeneratorMapping($class, $embeddableMetadata);
|
||||
}
|
||||
|
||||
$class->inlineEmbeddable($property, $embeddableMetadata);
|
||||
|
||||
unset($this->embeddablesActiveNesting[$class->name]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($parent) {
|
||||
if ($parent->isInheritanceTypeSingleTable()) {
|
||||
$class->setPrimaryTable($parent->table);
|
||||
}
|
||||
|
||||
$this->addInheritedIndexes($class, $parent);
|
||||
|
||||
if ($parent->cache) {
|
||||
$class->cache = $parent->cache;
|
||||
}
|
||||
|
||||
if ($parent->containsForeignIdentifier) {
|
||||
$class->containsForeignIdentifier = true;
|
||||
}
|
||||
|
||||
if ($parent->containsEnumIdentifier) {
|
||||
$class->containsEnumIdentifier = true;
|
||||
}
|
||||
|
||||
if (! empty($parent->entityListeners) && empty($class->entityListeners)) {
|
||||
$class->entityListeners = $parent->entityListeners;
|
||||
}
|
||||
}
|
||||
|
||||
$class->setParentClasses($nonSuperclassParents);
|
||||
|
||||
if ($class->isRootEntity() && ! $class->isInheritanceTypeNone() && ! $class->discriminatorMap) {
|
||||
$this->addDefaultDiscriminatorMap($class);
|
||||
}
|
||||
|
||||
// During the following event, there may also be updates to the discriminator map as per GH-1257/GH-8402.
|
||||
// So, we must not discover the missing subclasses before that.
|
||||
|
||||
if ($this->evm->hasListeners(Events::loadClassMetadata)) {
|
||||
$eventArgs = new LoadClassMetadataEventArgs($class, $this->em);
|
||||
$this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs);
|
||||
}
|
||||
|
||||
$this->findAbstractEntityClassesNotListedInDiscriminatorMap($class);
|
||||
|
||||
$this->validateRuntimeMetadata($class, $parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate runtime metadata is correctly defined.
|
||||
*
|
||||
* @throws MappingException
|
||||
*/
|
||||
protected function validateRuntimeMetadata(ClassMetadata $class, ClassMetadataInterface|null $parent): void
|
||||
{
|
||||
if (! $class->reflClass) {
|
||||
// only validate if there is a reflection class instance
|
||||
return;
|
||||
}
|
||||
|
||||
$class->validateIdentifier();
|
||||
$class->validateAssociations();
|
||||
$class->validateLifecycleCallbacks($this->getReflectionService());
|
||||
|
||||
// verify inheritance
|
||||
if (! $class->isMappedSuperclass && ! $class->isInheritanceTypeNone()) {
|
||||
if (! $parent) {
|
||||
if (count($class->discriminatorMap) === 0) {
|
||||
throw MappingException::missingDiscriminatorMap($class->name);
|
||||
}
|
||||
|
||||
if (! $class->discriminatorColumn) {
|
||||
throw MappingException::missingDiscriminatorColumn($class->name);
|
||||
}
|
||||
|
||||
foreach ($class->subClasses as $subClass) {
|
||||
if ((new ReflectionClass($subClass))->name !== $subClass) {
|
||||
throw MappingException::invalidClassInDiscriminatorMap($subClass, $class->name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert($parent instanceof ClassMetadata); // https://github.com/doctrine/orm/issues/8746
|
||||
if (
|
||||
! $class->reflClass->isAbstract()
|
||||
&& ! in_array($class->name, $class->discriminatorMap, true)
|
||||
) {
|
||||
throw MappingException::mappedClassNotPartOfDiscriminatorMap($class->name, $class->rootEntityName);
|
||||
}
|
||||
}
|
||||
} elseif ($class->isMappedSuperclass && $class->name === $class->rootEntityName && (count($class->discriminatorMap) || $class->discriminatorColumn)) {
|
||||
// second condition is necessary for mapped superclasses in the middle of an inheritance hierarchy
|
||||
throw MappingException::noInheritanceOnMappedSuperClass($class->name);
|
||||
}
|
||||
}
|
||||
|
||||
protected function newClassMetadataInstance(string $className): ClassMetadata
|
||||
{
|
||||
return new ClassMetadata(
|
||||
$className,
|
||||
$this->em->getConfiguration()->getNamingStrategy(),
|
||||
$this->em->getConfiguration()->getTypedFieldMapper(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a default discriminator map if no one is given
|
||||
*
|
||||
* If an entity is of any inheritance type and does not contain a
|
||||
* discriminator map, then the map is generated automatically. This process
|
||||
* is expensive computation wise.
|
||||
*
|
||||
* The automatically generated discriminator map contains the lowercase short name of
|
||||
* each class as key.
|
||||
*
|
||||
* @throws MappingException
|
||||
*/
|
||||
private function addDefaultDiscriminatorMap(ClassMetadata $class): void
|
||||
{
|
||||
$allClasses = $this->driver->getAllClassNames();
|
||||
$fqcn = $class->getName();
|
||||
$map = [$this->getShortName($class->name) => $fqcn];
|
||||
|
||||
$duplicates = [];
|
||||
foreach ($allClasses as $subClassCandidate) {
|
||||
if (is_subclass_of($subClassCandidate, $fqcn)) {
|
||||
$shortName = $this->getShortName($subClassCandidate);
|
||||
|
||||
if (isset($map[$shortName])) {
|
||||
$duplicates[] = $shortName;
|
||||
}
|
||||
|
||||
$map[$shortName] = $subClassCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
if ($duplicates) {
|
||||
throw MappingException::duplicateDiscriminatorEntry($class->name, $duplicates, $map);
|
||||
}
|
||||
|
||||
$class->setDiscriminatorMap($map);
|
||||
}
|
||||
|
||||
private function findAbstractEntityClassesNotListedInDiscriminatorMap(ClassMetadata $rootEntityClass): void
|
||||
{
|
||||
// Only root classes in inheritance hierarchies need contain a discriminator map,
|
||||
// so skip for other classes.
|
||||
if (! $rootEntityClass->isRootEntity() || $rootEntityClass->isInheritanceTypeNone()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$processedClasses = [$rootEntityClass->name => true];
|
||||
foreach ($rootEntityClass->subClasses as $knownSubClass) {
|
||||
$processedClasses[$knownSubClass] = true;
|
||||
}
|
||||
|
||||
foreach ($rootEntityClass->discriminatorMap as $declaredClassName) {
|
||||
// This fetches non-transient parent classes only
|
||||
$parentClasses = $this->getParentClasses($declaredClassName);
|
||||
|
||||
foreach ($parentClasses as $parentClass) {
|
||||
if (isset($processedClasses[$parentClass])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$processedClasses[$parentClass] = true;
|
||||
|
||||
// All non-abstract entity classes must be listed in the discriminator map, and
|
||||
// this will be validated/enforced at runtime (possibly at a later time, when the
|
||||
// subclass is loaded, but anyways). Also, subclasses is about entity classes only.
|
||||
// That means we can ignore non-abstract classes here. The (expensive) driver
|
||||
// check for mapped superclasses need only be run for abstract candidate classes.
|
||||
if (! (new ReflectionClass($parentClass))->isAbstract() || $this->peekIfIsMappedSuperclass($parentClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have found a non-transient, non-mapped-superclass = an entity class (possibly abstract, but that does not matter)
|
||||
$rootEntityClass->addSubClass($parentClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @param class-string $className */
|
||||
private function peekIfIsMappedSuperclass(string $className): bool
|
||||
{
|
||||
$reflService = $this->getReflectionService();
|
||||
$class = $this->newClassMetadataInstance($className);
|
||||
$this->initializeReflection($class, $reflService);
|
||||
|
||||
$this->getDriver()->loadMetadataForClass($className, $class);
|
||||
|
||||
return $class->isMappedSuperclass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lower-case short name of a class.
|
||||
*
|
||||
* @param class-string $className
|
||||
*/
|
||||
private function getShortName(string $className): string
|
||||
{
|
||||
if (! str_contains($className, '\\')) {
|
||||
return strtolower($className);
|
||||
}
|
||||
|
||||
$parts = explode('\\', $className);
|
||||
|
||||
return strtolower(end($parts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the `inherited` and `declared` values into mapping information for fields, associations
|
||||
* and embedded classes.
|
||||
*/
|
||||
private function addMappingInheritanceInformation(
|
||||
AssociationMapping|EmbeddedClassMapping|FieldMapping $mapping,
|
||||
ClassMetadata $parentClass,
|
||||
): void {
|
||||
if (! isset($mapping->inherited) && ! $parentClass->isMappedSuperclass) {
|
||||
$mapping->inherited = $parentClass->name;
|
||||
}
|
||||
|
||||
if (! isset($mapping->declared)) {
|
||||
$mapping->declared = $parentClass->name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds inherited fields to the subclass mapping.
|
||||
*/
|
||||
private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass): void
|
||||
{
|
||||
foreach ($parentClass->fieldMappings as $mapping) {
|
||||
$subClassMapping = clone $mapping;
|
||||
$this->addMappingInheritanceInformation($subClassMapping, $parentClass);
|
||||
$subClass->addInheritedFieldMapping($subClassMapping);
|
||||
}
|
||||
|
||||
foreach ($parentClass->propertyAccessors as $name => $field) {
|
||||
$subClass->propertyAccessors[$name] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds inherited association mappings to the subclass mapping.
|
||||
*
|
||||
* @throws MappingException
|
||||
*/
|
||||
private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass): void
|
||||
{
|
||||
foreach ($parentClass->associationMappings as $field => $mapping) {
|
||||
$subClassMapping = clone $mapping;
|
||||
$this->addMappingInheritanceInformation($subClassMapping, $parentClass);
|
||||
// When the class inheriting the relation ($subClass) is the first entity class since the
|
||||
// relation has been defined in a mapped superclass (or in a chain
|
||||
// of mapped superclasses) above, then declare this current entity class as the source of
|
||||
// the relationship.
|
||||
// According to the definitions given in https://github.com/doctrine/orm/pull/10396/,
|
||||
// this is the case <=> ! isset($mapping['inherited']).
|
||||
if (! isset($subClassMapping->inherited)) {
|
||||
$subClassMapping->sourceEntity = $subClass->name;
|
||||
}
|
||||
|
||||
$subClass->addInheritedAssociationMapping($subClassMapping);
|
||||
}
|
||||
}
|
||||
|
||||
private function addInheritedEmbeddedClasses(ClassMetadata $subClass, ClassMetadata $parentClass): void
|
||||
{
|
||||
foreach ($parentClass->embeddedClasses as $field => $embeddedClass) {
|
||||
$subClassMapping = clone $embeddedClass;
|
||||
$this->addMappingInheritanceInformation($subClassMapping, $parentClass);
|
||||
$subClass->embeddedClasses[$field] = $subClassMapping;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds nested embedded classes metadata to a parent class.
|
||||
*
|
||||
* @param ClassMetadata $subClass Sub embedded class metadata to add nested embedded classes metadata from.
|
||||
* @param ClassMetadata $parentClass Parent class to add nested embedded classes metadata to.
|
||||
* @param string $prefix Embedded classes' prefix to use for nested embedded classes field names.
|
||||
*/
|
||||
private function addNestedEmbeddedClasses(
|
||||
ClassMetadata $subClass,
|
||||
ClassMetadata $parentClass,
|
||||
string $prefix,
|
||||
): void {
|
||||
foreach ($subClass->embeddedClasses as $property => $embeddableClass) {
|
||||
if (isset($embeddableClass->inherited)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$embeddableMetadata = $this->getMetadataFor($embeddableClass->class);
|
||||
|
||||
$parentClass->mapEmbedded(
|
||||
[
|
||||
'fieldName' => $prefix . '.' . $property,
|
||||
'class' => $embeddableMetadata->name,
|
||||
'columnPrefix' => $embeddableClass->columnPrefix,
|
||||
'declaredField' => $embeddableClass->declaredField
|
||||
? $prefix . '.' . $embeddableClass->declaredField
|
||||
: $prefix,
|
||||
'originalField' => $embeddableClass->originalField ?: $property,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the table indices from the parent class superclass to the child class
|
||||
*/
|
||||
private function addInheritedIndexes(ClassMetadata $subClass, ClassMetadata $parentClass): void
|
||||
{
|
||||
if (! $parentClass->isMappedSuperclass) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (['uniqueConstraints', 'indexes'] as $indexType) {
|
||||
if (isset($parentClass->table[$indexType])) {
|
||||
foreach ($parentClass->table[$indexType] as $indexName => $index) {
|
||||
if (isset($subClass->table[$indexType][$indexName])) {
|
||||
continue; // Let the inheriting table override indices
|
||||
}
|
||||
|
||||
$subClass->table[$indexType][$indexName] = $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes the ID generator mapping. If "auto" is specified we choose the generator
|
||||
* most appropriate for the targeted database platform.
|
||||
*
|
||||
* @throws ORMException
|
||||
*/
|
||||
private function completeIdGeneratorMapping(ClassMetadata $class): void
|
||||
{
|
||||
$idGenType = $class->generatorType;
|
||||
if ($idGenType === ClassMetadata::GENERATOR_TYPE_AUTO) {
|
||||
$class->setIdGeneratorType($this->determineIdGeneratorStrategy($this->getTargetPlatform()));
|
||||
}
|
||||
|
||||
// Create & assign an appropriate ID generator instance
|
||||
switch ($class->generatorType) {
|
||||
case ClassMetadata::GENERATOR_TYPE_IDENTITY:
|
||||
$sequenceName = null;
|
||||
$fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null;
|
||||
$platform = $this->getTargetPlatform();
|
||||
|
||||
$generator = $fieldName && $class->fieldMappings[$fieldName]->type === 'bigint'
|
||||
? new BigIntegerIdentityGenerator()
|
||||
: new IdentityGenerator();
|
||||
|
||||
$class->setIdGenerator($generator);
|
||||
|
||||
break;
|
||||
|
||||
case ClassMetadata::GENERATOR_TYPE_SEQUENCE:
|
||||
// If there is no sequence definition yet, create a default definition
|
||||
$definition = $class->sequenceGeneratorDefinition;
|
||||
|
||||
if (! $definition) {
|
||||
$fieldName = $class->getSingleIdentifierFieldName();
|
||||
$sequenceName = $class->getSequenceName($this->getTargetPlatform());
|
||||
$quoted = isset($class->fieldMappings[$fieldName]->quoted) || isset($class->table['quoted']);
|
||||
|
||||
$definition = [
|
||||
'sequenceName' => $this->truncateSequenceName($sequenceName),
|
||||
'allocationSize' => 1,
|
||||
'initialValue' => 1,
|
||||
];
|
||||
|
||||
if ($quoted) {
|
||||
$definition['quoted'] = true;
|
||||
}
|
||||
|
||||
$class->setSequenceGeneratorDefinition($definition);
|
||||
}
|
||||
|
||||
$sequenceGenerator = new SequenceGenerator(
|
||||
$this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->getTargetPlatform()),
|
||||
(int) $definition['allocationSize'],
|
||||
);
|
||||
$class->setIdGenerator($sequenceGenerator);
|
||||
break;
|
||||
|
||||
case ClassMetadata::GENERATOR_TYPE_NONE:
|
||||
$class->setIdGenerator(new AssignedGenerator());
|
||||
break;
|
||||
|
||||
case ClassMetadata::GENERATOR_TYPE_CUSTOM:
|
||||
$definition = $class->customGeneratorDefinition;
|
||||
if ($definition === null) {
|
||||
throw InvalidCustomGenerator::onClassNotConfigured();
|
||||
}
|
||||
|
||||
if (! class_exists($definition['class'])) {
|
||||
throw InvalidCustomGenerator::onMissingClass($definition);
|
||||
}
|
||||
|
||||
$class->setIdGenerator(new $definition['class']());
|
||||
break;
|
||||
|
||||
default:
|
||||
throw UnknownGeneratorType::create($class->generatorType);
|
||||
}
|
||||
}
|
||||
|
||||
/** @phpstan-return ClassMetadata::GENERATOR_TYPE_* */
|
||||
private function determineIdGeneratorStrategy(AbstractPlatform $platform): int
|
||||
{
|
||||
assert($this->em !== null);
|
||||
foreach ($this->em->getConfiguration()->getIdentityGenerationPreferences() as $platformFamily => $strategy) {
|
||||
if (is_a($platform, $platformFamily)) {
|
||||
return $strategy;
|
||||
}
|
||||
}
|
||||
|
||||
$nonIdentityDefaultStrategy = self::NON_IDENTITY_DEFAULT_STRATEGY;
|
||||
|
||||
// DBAL 3
|
||||
if (method_exists($platform, 'getIdentitySequenceName')) {
|
||||
$nonIdentityDefaultStrategy[Platforms\PostgreSQLPlatform::class] = ClassMetadata::GENERATOR_TYPE_SEQUENCE;
|
||||
}
|
||||
|
||||
foreach ($nonIdentityDefaultStrategy as $platformFamily => $strategy) {
|
||||
if (is_a($platform, $platformFamily)) {
|
||||
if ($platform instanceof Platforms\PostgreSQLPlatform) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/issues/8893',
|
||||
<<<'DEPRECATION'
|
||||
Relying on non-optimal defaults for ID generation is deprecated, and IDENTITY
|
||||
results in SERIAL, which is not recommended.
|
||||
Instead, configure identifier generation strategies explicitly through
|
||||
configuration.
|
||||
We currently recommend "SEQUENCE" for "%s", when using DBAL 3,
|
||||
and "IDENTITY" when using DBAL 4,
|
||||
so you should probably use the following configuration before upgrading to DBAL 4,
|
||||
and remove it after deploying that upgrade:
|
||||
|
||||
$configuration->setIdentityGenerationPreferences([
|
||||
"%s" => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
|
||||
]);
|
||||
|
||||
DEPRECATION,
|
||||
$platformFamily,
|
||||
$platformFamily,
|
||||
);
|
||||
}
|
||||
|
||||
return $strategy;
|
||||
}
|
||||
}
|
||||
|
||||
return ClassMetadata::GENERATOR_TYPE_IDENTITY;
|
||||
}
|
||||
|
||||
private function truncateSequenceName(string $schemaElementName): string
|
||||
{
|
||||
$platform = $this->getTargetPlatform();
|
||||
if (! $platform instanceof Platforms\OraclePlatform) {
|
||||
return $schemaElementName;
|
||||
}
|
||||
|
||||
$maxIdentifierLength = $platform->getMaxIdentifierLength();
|
||||
|
||||
if (strlen($schemaElementName) > $maxIdentifierLength) {
|
||||
return substr($schemaElementName, 0, $maxIdentifierLength);
|
||||
}
|
||||
|
||||
return $schemaElementName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherits the ID generator mapping from a parent class.
|
||||
*/
|
||||
private function inheritIdGeneratorMapping(ClassMetadata $class, ClassMetadata $parent): void
|
||||
{
|
||||
if ($parent->isIdGeneratorSequence()) {
|
||||
$class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition);
|
||||
}
|
||||
|
||||
if ($parent->generatorType) {
|
||||
$class->setIdGeneratorType($parent->generatorType);
|
||||
}
|
||||
|
||||
if ($parent->idGenerator ?? null) {
|
||||
$class->setIdGenerator($parent->idGenerator);
|
||||
}
|
||||
}
|
||||
|
||||
protected function wakeupReflection(ClassMetadataInterface $class, ReflectionService $reflService): void
|
||||
{
|
||||
$class->wakeupReflection($reflService);
|
||||
|
||||
if (PHP_VERSION_ID < 80400) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($class->propertyAccessors as $propertyAccessor) {
|
||||
$property = $propertyAccessor->getUnderlyingReflector();
|
||||
|
||||
if ($property->isVirtual()) {
|
||||
throw MappingException::mappingVirtualPropertyNotAllowed($class->name, $property->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function initializeReflection(ClassMetadataInterface $class, ReflectionService $reflService): void
|
||||
{
|
||||
$class->initializeReflection($reflService);
|
||||
}
|
||||
|
||||
protected function getDriver(): MappingDriver
|
||||
{
|
||||
assert($this->driver !== null);
|
||||
|
||||
return $this->driver;
|
||||
}
|
||||
|
||||
protected function isEntity(ClassMetadataInterface $class): bool
|
||||
{
|
||||
return ! $class->isMappedSuperclass;
|
||||
}
|
||||
|
||||
private function getTargetPlatform(): Platforms\AbstractPlatform
|
||||
{
|
||||
if (! $this->targetPlatform) {
|
||||
$this->targetPlatform = $this->em->getConnection()->getDatabasePlatform();
|
||||
}
|
||||
|
||||
return $this->targetPlatform;
|
||||
}
|
||||
}
|
||||
37
backend/vendor/doctrine/orm/src/Mapping/Column.php
vendored
Normal file
37
backend/vendor/doctrine/orm/src/Mapping/Column.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
use BackedEnum;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class Column implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* @param int|null $precision The precision for a decimal (exact numeric) column (Applies only for decimal column).
|
||||
* @param int|null $scale The scale for a decimal (exact numeric) column (Applies only for decimal column).
|
||||
* @param class-string<BackedEnum>|null $enumType
|
||||
* @param array<string,mixed> $options
|
||||
* @phpstan-param 'NEVER'|'INSERT'|'ALWAYS'|null $generated
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string|null $name = null,
|
||||
public readonly string|null $type = null,
|
||||
public readonly int|null $length = null,
|
||||
public readonly int|null $precision = null,
|
||||
public readonly int|null $scale = null,
|
||||
public readonly bool $unique = false,
|
||||
public readonly bool $nullable = false,
|
||||
public readonly bool $insertable = true,
|
||||
public readonly bool $updatable = true,
|
||||
public readonly string|null $enumType = null,
|
||||
public readonly array $options = [],
|
||||
public readonly string|null $columnDefinition = null,
|
||||
public readonly string|null $generated = null,
|
||||
public readonly bool $index = false,
|
||||
) {
|
||||
}
|
||||
}
|
||||
16
backend/vendor/doctrine/orm/src/Mapping/CustomIdGenerator.php
vendored
Normal file
16
backend/vendor/doctrine/orm/src/Mapping/CustomIdGenerator.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class CustomIdGenerator implements MappingAttribute
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string|null $class = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
40
backend/vendor/doctrine/orm/src/Mapping/DefaultEntityListenerResolver.php
vendored
Normal file
40
backend/vendor/doctrine/orm/src/Mapping/DefaultEntityListenerResolver.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use function trim;
|
||||
|
||||
/**
|
||||
* The default DefaultEntityListener
|
||||
*/
|
||||
class DefaultEntityListenerResolver implements EntityListenerResolver
|
||||
{
|
||||
/** @var array<class-string, object> Map to store entity listener instances. */
|
||||
private array $instances = [];
|
||||
|
||||
public function clear(string|null $className = null): void
|
||||
{
|
||||
if ($className === null) {
|
||||
$this->instances = [];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$className = trim($className, '\\');
|
||||
unset($this->instances[$className]);
|
||||
}
|
||||
|
||||
public function register(object $object): void
|
||||
{
|
||||
$this->instances[$object::class] = $object;
|
||||
}
|
||||
|
||||
public function resolve(string $className): object
|
||||
{
|
||||
$className = trim($className, '\\');
|
||||
|
||||
return $this->instances[$className] ??= new $className();
|
||||
}
|
||||
}
|
||||
68
backend/vendor/doctrine/orm/src/Mapping/DefaultNamingStrategy.php
vendored
Normal file
68
backend/vendor/doctrine/orm/src/Mapping/DefaultNamingStrategy.php
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use function str_contains;
|
||||
use function strrpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* The default NamingStrategy
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
*/
|
||||
class DefaultNamingStrategy implements NamingStrategy
|
||||
{
|
||||
public function classToTableName(string $className): string
|
||||
{
|
||||
if (str_contains($className, '\\')) {
|
||||
return substr($className, strrpos($className, '\\') + 1);
|
||||
}
|
||||
|
||||
return $className;
|
||||
}
|
||||
|
||||
public function propertyToColumnName(string $propertyName, string $className): string
|
||||
{
|
||||
return $propertyName;
|
||||
}
|
||||
|
||||
public function embeddedFieldToColumnName(
|
||||
string $propertyName,
|
||||
string $embeddedColumnName,
|
||||
string $className,
|
||||
string $embeddedClassName,
|
||||
): string {
|
||||
return $propertyName . '_' . $embeddedColumnName;
|
||||
}
|
||||
|
||||
public function referenceColumnName(): string
|
||||
{
|
||||
return 'id';
|
||||
}
|
||||
|
||||
public function joinColumnName(string $propertyName, string $className): string
|
||||
{
|
||||
return $propertyName . '_' . $this->referenceColumnName();
|
||||
}
|
||||
|
||||
public function joinTableName(
|
||||
string $sourceEntity,
|
||||
string $targetEntity,
|
||||
string $propertyName,
|
||||
): string {
|
||||
return strtolower($this->classToTableName($sourceEntity) . '_' .
|
||||
$this->classToTableName($targetEntity));
|
||||
}
|
||||
|
||||
public function joinKeyColumnName(
|
||||
string $entityName,
|
||||
string|null $referencedColumnName,
|
||||
): string {
|
||||
return strtolower($this->classToTableName($entityName) . '_' .
|
||||
($referencedColumnName ?: $this->referenceColumnName()));
|
||||
}
|
||||
}
|
||||
157
backend/vendor/doctrine/orm/src/Mapping/DefaultQuoteStrategy.php
vendored
Normal file
157
backend/vendor/doctrine/orm/src/Mapping/DefaultQuoteStrategy.php
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\ORM\Internal\SQLResultCasing;
|
||||
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function assert;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function is_numeric;
|
||||
use function preg_replace;
|
||||
use function sprintf;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* A set of rules for determining the physical column, alias and table quotes
|
||||
*/
|
||||
class DefaultQuoteStrategy implements QuoteStrategy
|
||||
{
|
||||
use SQLResultCasing;
|
||||
|
||||
public function getColumnName(string $fieldName, ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
return isset($class->fieldMappings[$fieldName]->quoted)
|
||||
? $platform->quoteSingleIdentifier($class->fieldMappings[$fieldName]->columnName)
|
||||
: $class->fieldMappings[$fieldName]->columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @todo Table names should be computed in DBAL depending on the platform
|
||||
*/
|
||||
public function getTableName(ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
$tableName = $class->table['name'];
|
||||
|
||||
if (! empty($class->table['schema'])) {
|
||||
return isset($class->table['quoted'])
|
||||
? sprintf(
|
||||
'%s.%s',
|
||||
$platform->quoteSingleIdentifier($class->table['schema']),
|
||||
$platform->quoteSingleIdentifier($tableName),
|
||||
)
|
||||
: $class->table['schema'] . '.' . $class->table['name'];
|
||||
}
|
||||
|
||||
return isset($class->table['quoted'])
|
||||
? $platform->quoteSingleIdentifier($tableName)
|
||||
: $tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
return isset($definition['quoted'])
|
||||
? implode('.', array_map(
|
||||
static fn (string $part) => $platform->quoteSingleIdentifier($part),
|
||||
explode('.', $definition['sequenceName']),
|
||||
))
|
||||
: $definition['sequenceName'];
|
||||
}
|
||||
|
||||
public function getJoinColumnName(JoinColumnMapping $joinColumn, ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
return isset($joinColumn->quoted)
|
||||
? $platform->quoteSingleIdentifier($joinColumn->name)
|
||||
: $joinColumn->name;
|
||||
}
|
||||
|
||||
public function getReferencedJoinColumnName(
|
||||
JoinColumnMapping $joinColumn,
|
||||
ClassMetadata $class,
|
||||
AbstractPlatform $platform,
|
||||
): string {
|
||||
return isset($joinColumn->quoted)
|
||||
? $platform->quoteSingleIdentifier($joinColumn->referencedColumnName)
|
||||
: $joinColumn->referencedColumnName;
|
||||
}
|
||||
|
||||
public function getJoinTableName(
|
||||
ManyToManyOwningSideMapping $association,
|
||||
ClassMetadata $class,
|
||||
AbstractPlatform $platform,
|
||||
): string {
|
||||
$schema = '';
|
||||
|
||||
if (isset($association->joinTable->schema)) {
|
||||
$schema = $association->joinTable->schema . '.';
|
||||
}
|
||||
|
||||
$tableName = $association->joinTable->name;
|
||||
|
||||
if (isset($association->joinTable->quoted)) {
|
||||
$tableName = $platform->quoteSingleIdentifier($tableName);
|
||||
}
|
||||
|
||||
return $schema . $tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform): array
|
||||
{
|
||||
$quotedColumnNames = [];
|
||||
|
||||
foreach ($class->identifier as $fieldName) {
|
||||
if (isset($class->fieldMappings[$fieldName])) {
|
||||
$quotedColumnNames[] = $this->getColumnName($fieldName, $class, $platform);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Association defined as Id field
|
||||
$assoc = $class->associationMappings[$fieldName];
|
||||
assert($assoc->isToOneOwningSide());
|
||||
$joinColumns = $assoc->joinColumns;
|
||||
$assocQuotedColumnNames = array_map(
|
||||
static fn (JoinColumnMapping $joinColumn) => isset($joinColumn->quoted)
|
||||
? $platform->quoteSingleIdentifier($joinColumn->name)
|
||||
: $joinColumn->name,
|
||||
$joinColumns,
|
||||
);
|
||||
|
||||
$quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames);
|
||||
}
|
||||
|
||||
return $quotedColumnNames;
|
||||
}
|
||||
|
||||
public function getColumnAlias(
|
||||
string $columnName,
|
||||
int $counter,
|
||||
AbstractPlatform $platform,
|
||||
ClassMetadata|null $class = null,
|
||||
): string {
|
||||
// 1 ) Concatenate column name and counter
|
||||
// 2 ) Trim the column alias to the maximum identifier length of the platform.
|
||||
// If the alias is to long, characters are cut off from the beginning.
|
||||
// 3 ) Strip non alphanumeric characters
|
||||
// 4 ) Prefix with "_" if the result its numeric
|
||||
$columnName .= '_' . $counter;
|
||||
$columnName = substr($columnName, -$platform->getMaxIdentifierLength());
|
||||
$columnName = preg_replace('/[^A-Za-z0-9_]/', '', $columnName);
|
||||
$columnName = is_numeric($columnName) ? '_' . $columnName : $columnName;
|
||||
|
||||
return $this->getSQLResultCasing($platform, $columnName);
|
||||
}
|
||||
}
|
||||
95
backend/vendor/doctrine/orm/src/Mapping/DefaultTypedFieldMapper.php
vendored
Normal file
95
backend/vendor/doctrine/orm/src/Mapping/DefaultTypedFieldMapper.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use BackedEnum;
|
||||
use BcMath\Number;
|
||||
use DateInterval;
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use ReflectionEnum;
|
||||
use ReflectionNamedType;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function array_merge;
|
||||
use function assert;
|
||||
use function defined;
|
||||
use function enum_exists;
|
||||
use function is_a;
|
||||
|
||||
/** @phpstan-type ScalarName = 'array'|'bool'|'float'|'int'|'string' */
|
||||
final class DefaultTypedFieldMapper implements TypedFieldMapper
|
||||
{
|
||||
/** @var array<class-string|ScalarName, class-string<Type>|string> $typedFieldMappings */
|
||||
private array $typedFieldMappings;
|
||||
|
||||
private const DEFAULT_TYPED_FIELD_MAPPINGS = [
|
||||
DateInterval::class => Types::DATEINTERVAL,
|
||||
DateTime::class => Types::DATETIME_MUTABLE,
|
||||
DateTimeImmutable::class => Types::DATETIME_IMMUTABLE,
|
||||
'array' => Types::JSON,
|
||||
'bool' => Types::BOOLEAN,
|
||||
'float' => Types::FLOAT,
|
||||
'int' => Types::INTEGER,
|
||||
'string' => Types::STRING,
|
||||
];
|
||||
|
||||
/** @param array<class-string|ScalarName, class-string<Type>|string> $typedFieldMappings */
|
||||
public function __construct(array $typedFieldMappings = [])
|
||||
{
|
||||
$defaultMappings = self::DEFAULT_TYPED_FIELD_MAPPINGS;
|
||||
if (defined(Types::class . '::NUMBER')) { // DBAL 4.3+
|
||||
$defaultMappings[Number::class] = Types::NUMBER;
|
||||
}
|
||||
|
||||
$this->typedFieldMappings = array_merge($defaultMappings, $typedFieldMappings);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function validateAndComplete(array $mapping, ReflectionProperty $field): array
|
||||
{
|
||||
$type = $field->getType();
|
||||
|
||||
if (! $type instanceof ReflectionNamedType) {
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
if (
|
||||
! $type->isBuiltin()
|
||||
&& enum_exists($type->getName())
|
||||
&& (! isset($mapping['type']) || (
|
||||
defined('Doctrine\DBAL\Types\Types::ENUM')
|
||||
&& $mapping['type'] === Types::ENUM
|
||||
))
|
||||
) {
|
||||
$reflection = new ReflectionEnum($type->getName());
|
||||
if (! $reflection->isBacked()) {
|
||||
throw MappingException::backedEnumTypeRequired(
|
||||
$field->class,
|
||||
$mapping['fieldName'],
|
||||
$type->getName(),
|
||||
);
|
||||
}
|
||||
|
||||
assert(is_a($type->getName(), BackedEnum::class, true));
|
||||
$mapping['enumType'] = $type->getName();
|
||||
$type = $reflection->getBackingType();
|
||||
}
|
||||
|
||||
if (isset($mapping['type'])) {
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
if (isset($this->typedFieldMappings[$type->getName()])) {
|
||||
$mapping['type'] = $this->typedFieldMappings[$type->getName()];
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
}
|
||||
24
backend/vendor/doctrine/orm/src/Mapping/DiscriminatorColumn.php
vendored
Normal file
24
backend/vendor/doctrine/orm/src/Mapping/DiscriminatorColumn.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
use BackedEnum;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class DiscriminatorColumn implements MappingAttribute
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string|null $name = null,
|
||||
public readonly string|null $type = null,
|
||||
public readonly int|null $length = null,
|
||||
public readonly string|null $columnDefinition = null,
|
||||
/** @var class-string<BackedEnum>|null */
|
||||
public readonly string|null $enumType = null,
|
||||
/** @var array<string, mixed> */
|
||||
public readonly array $options = [],
|
||||
) {
|
||||
}
|
||||
}
|
||||
83
backend/vendor/doctrine/orm/src/Mapping/DiscriminatorColumnMapping.php
vendored
Normal file
83
backend/vendor/doctrine/orm/src/Mapping/DiscriminatorColumnMapping.php
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use ArrayAccess;
|
||||
use BackedEnum;
|
||||
use Exception;
|
||||
|
||||
use function in_array;
|
||||
use function property_exists;
|
||||
|
||||
/** @template-implements ArrayAccess<string, mixed> */
|
||||
final class DiscriminatorColumnMapping implements ArrayAccess
|
||||
{
|
||||
use ArrayAccessImplementation;
|
||||
|
||||
/** The database length of the column. Optional. Default value taken from the type. */
|
||||
public int|null $length = null;
|
||||
|
||||
public string|null $columnDefinition = null;
|
||||
|
||||
/** @var class-string<BackedEnum>|null */
|
||||
public string|null $enumType = null;
|
||||
|
||||
/** @var array<string, mixed> */
|
||||
public array $options = [];
|
||||
|
||||
public function __construct(
|
||||
public string $type,
|
||||
public string $fieldName,
|
||||
public string $name,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param array{
|
||||
* type: string,
|
||||
* fieldName: string,
|
||||
* name: string,
|
||||
* length?: int|null,
|
||||
* columnDefinition?: string|null,
|
||||
* enumType?: class-string<BackedEnum>|null,
|
||||
* options?: array<string, mixed>|null,
|
||||
* } $mappingArray
|
||||
*/
|
||||
public static function fromMappingArray(array $mappingArray): self
|
||||
{
|
||||
$mapping = new self(
|
||||
$mappingArray['type'],
|
||||
$mappingArray['fieldName'],
|
||||
$mappingArray['name'],
|
||||
);
|
||||
foreach ($mappingArray as $key => $value) {
|
||||
if (in_array($key, ['type', 'fieldName', 'name'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property_exists($mapping, $key)) {
|
||||
$mapping->$key = $value ?? $mapping->$key;
|
||||
} else {
|
||||
throw new Exception('Unknown property ' . $key . ' on class ' . static::class);
|
||||
}
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function __sleep(): array
|
||||
{
|
||||
$serialized = ['type', 'fieldName', 'name'];
|
||||
|
||||
foreach (['length', 'columnDefinition', 'enumType', 'options'] as $stringOrArrayKey) {
|
||||
if ($this->$stringOrArrayKey !== null) {
|
||||
$serialized[] = $stringOrArrayKey;
|
||||
}
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Mapping/DiscriminatorMap.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Mapping/DiscriminatorMap.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class DiscriminatorMap implements MappingAttribute
|
||||
{
|
||||
/** @param array<int|string, string> $value */
|
||||
public function __construct(
|
||||
public readonly array $value,
|
||||
) {
|
||||
}
|
||||
}
|
||||
770
backend/vendor/doctrine/orm/src/Mapping/Driver/AttributeDriver.php
vendored
Normal file
770
backend/vendor/doctrine/orm/src/Mapping/Driver/AttributeDriver.php
vendored
Normal file
@@ -0,0 +1,770 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\ORM\Events;
|
||||
use Doctrine\ORM\Mapping;
|
||||
use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata as PersistenceClassMetadata;
|
||||
use Doctrine\Persistence\Mapping\Driver\ClassLocator;
|
||||
use Doctrine\Persistence\Mapping\Driver\ColocatedMappingDriver;
|
||||
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
|
||||
use InvalidArgumentException;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
|
||||
use function assert;
|
||||
use function class_exists;
|
||||
use function constant;
|
||||
use function defined;
|
||||
use function sprintf;
|
||||
|
||||
class AttributeDriver implements MappingDriver
|
||||
{
|
||||
use ColocatedMappingDriver;
|
||||
use ReflectionBasedDriver;
|
||||
|
||||
private const ENTITY_ATTRIBUTE_CLASSES = [
|
||||
Mapping\Entity::class => 1,
|
||||
Mapping\MappedSuperclass::class => 2,
|
||||
];
|
||||
|
||||
private readonly AttributeReader $reader;
|
||||
|
||||
/**
|
||||
* @param string[]|ClassLocator $paths a ClassLocator, or an array of directories.
|
||||
* @param true $reportFieldsWhereDeclared no-op, to be removed in 4.0
|
||||
*/
|
||||
public function __construct(array|ClassLocator $paths, bool $reportFieldsWhereDeclared = true)
|
||||
{
|
||||
if (! $reportFieldsWhereDeclared) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'The $reportFieldsWhereDeclared argument is no longer supported, make sure to omit it when calling %s.',
|
||||
__METHOD__,
|
||||
));
|
||||
}
|
||||
|
||||
$this->reader = new AttributeReader();
|
||||
|
||||
if ($paths instanceof ClassLocator) {
|
||||
$this->classLocator = $paths;
|
||||
} else {
|
||||
$this->addPaths($paths);
|
||||
}
|
||||
}
|
||||
|
||||
public function isTransient(string $className): bool
|
||||
{
|
||||
$classAttributes = $this->reader->getClassAttributes(new ReflectionClass($className));
|
||||
|
||||
foreach ($classAttributes as $a) {
|
||||
$attr = $a instanceof RepeatableAttributeCollection ? $a[0] : $a;
|
||||
if (isset(self::ENTITY_ATTRIBUTE_CLASSES[$attr::class])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param class-string<T> $className
|
||||
* @param ClassMetadata<T> $metadata
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function loadMetadataForClass(string $className, PersistenceClassMetadata $metadata): void
|
||||
{
|
||||
$reflectionClass = $metadata->getReflectionClass()
|
||||
// this happens when running attribute driver in combination with
|
||||
// static reflection services. This is not the nicest fix
|
||||
?? new ReflectionClass($metadata->name);
|
||||
|
||||
$classAttributes = $this->reader->getClassAttributes($reflectionClass);
|
||||
|
||||
// Evaluate Entity attribute
|
||||
if (isset($classAttributes[Mapping\Entity::class])) {
|
||||
$entityAttribute = $classAttributes[Mapping\Entity::class];
|
||||
if ($entityAttribute->repositoryClass !== null) {
|
||||
$metadata->setCustomRepositoryClass($entityAttribute->repositoryClass);
|
||||
}
|
||||
|
||||
if ($entityAttribute->readOnly) {
|
||||
$metadata->markReadOnly();
|
||||
}
|
||||
} elseif (isset($classAttributes[Mapping\MappedSuperclass::class])) {
|
||||
$mappedSuperclassAttribute = $classAttributes[Mapping\MappedSuperclass::class];
|
||||
|
||||
$metadata->setCustomRepositoryClass($mappedSuperclassAttribute->repositoryClass);
|
||||
$metadata->isMappedSuperclass = true;
|
||||
} elseif (isset($classAttributes[Mapping\Embeddable::class])) {
|
||||
$metadata->isEmbeddedClass = true;
|
||||
} else {
|
||||
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
||||
}
|
||||
|
||||
$primaryTable = [];
|
||||
|
||||
if (isset($classAttributes[Mapping\Table::class])) {
|
||||
$tableAnnot = $classAttributes[Mapping\Table::class];
|
||||
$primaryTable['name'] = $tableAnnot->name;
|
||||
$primaryTable['schema'] = $tableAnnot->schema;
|
||||
|
||||
if ($tableAnnot->options) {
|
||||
$primaryTable['options'] = $tableAnnot->options;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($classAttributes[Mapping\Index::class])) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\Index::class);
|
||||
}
|
||||
|
||||
foreach ($classAttributes[Mapping\Index::class] as $idx => $indexAnnot) {
|
||||
$index = [];
|
||||
|
||||
if (! empty($indexAnnot->columns)) {
|
||||
$index['columns'] = $indexAnnot->columns;
|
||||
}
|
||||
|
||||
if (! empty($indexAnnot->fields)) {
|
||||
$index['fields'] = $indexAnnot->fields;
|
||||
}
|
||||
|
||||
if (
|
||||
isset($index['columns'], $index['fields'])
|
||||
|| (
|
||||
! isset($index['columns'])
|
||||
&& ! isset($index['fields'])
|
||||
)
|
||||
) {
|
||||
throw MappingException::invalidIndexConfiguration(
|
||||
$className,
|
||||
(string) ($indexAnnot->name ?? $idx),
|
||||
);
|
||||
}
|
||||
|
||||
if (! empty($indexAnnot->flags)) {
|
||||
$index['flags'] = $indexAnnot->flags;
|
||||
}
|
||||
|
||||
if (! empty($indexAnnot->options)) {
|
||||
$index['options'] = $indexAnnot->options;
|
||||
}
|
||||
|
||||
if (! empty($indexAnnot->name)) {
|
||||
$primaryTable['indexes'][$indexAnnot->name] = $index;
|
||||
} else {
|
||||
$primaryTable['indexes'][] = $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($classAttributes[Mapping\UniqueConstraint::class])) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\UniqueConstraint::class);
|
||||
}
|
||||
|
||||
foreach ($classAttributes[Mapping\UniqueConstraint::class] as $idx => $uniqueConstraintAnnot) {
|
||||
$uniqueConstraint = [];
|
||||
|
||||
if (! empty($uniqueConstraintAnnot->columns)) {
|
||||
$uniqueConstraint['columns'] = $uniqueConstraintAnnot->columns;
|
||||
}
|
||||
|
||||
if (! empty($uniqueConstraintAnnot->fields)) {
|
||||
$uniqueConstraint['fields'] = $uniqueConstraintAnnot->fields;
|
||||
}
|
||||
|
||||
if (
|
||||
isset($uniqueConstraint['columns'], $uniqueConstraint['fields'])
|
||||
|| (
|
||||
! isset($uniqueConstraint['columns'])
|
||||
&& ! isset($uniqueConstraint['fields'])
|
||||
)
|
||||
) {
|
||||
throw MappingException::invalidUniqueConstraintConfiguration(
|
||||
$className,
|
||||
(string) ($uniqueConstraintAnnot->name ?? $idx),
|
||||
);
|
||||
}
|
||||
|
||||
if (! empty($uniqueConstraintAnnot->options)) {
|
||||
$uniqueConstraint['options'] = $uniqueConstraintAnnot->options;
|
||||
}
|
||||
|
||||
if (! empty($uniqueConstraintAnnot->name)) {
|
||||
$primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint;
|
||||
} else {
|
||||
$primaryTable['uniqueConstraints'][] = $uniqueConstraint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$metadata->setPrimaryTable($primaryTable);
|
||||
|
||||
// Evaluate #[Cache] attribute
|
||||
if (isset($classAttributes[Mapping\Cache::class])) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\Cache::class);
|
||||
}
|
||||
|
||||
$cacheAttribute = $classAttributes[Mapping\Cache::class];
|
||||
$cacheMap = [
|
||||
'region' => $cacheAttribute->region,
|
||||
'usage' => constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $cacheAttribute->usage),
|
||||
];
|
||||
|
||||
$metadata->enableCache($cacheMap);
|
||||
}
|
||||
|
||||
// Evaluate InheritanceType attribute
|
||||
if (isset($classAttributes[Mapping\InheritanceType::class])) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\InheritanceType::class);
|
||||
}
|
||||
|
||||
$inheritanceTypeAttribute = $classAttributes[Mapping\InheritanceType::class];
|
||||
|
||||
$metadata->setInheritanceType(
|
||||
constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceTypeAttribute->value),
|
||||
);
|
||||
|
||||
if ($metadata->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||
// Evaluate DiscriminatorColumn attribute
|
||||
if (isset($classAttributes[Mapping\DiscriminatorColumn::class])) {
|
||||
$discrColumnAttribute = $classAttributes[Mapping\DiscriminatorColumn::class];
|
||||
assert($discrColumnAttribute instanceof Mapping\DiscriminatorColumn);
|
||||
|
||||
$columnDef = [
|
||||
'name' => $discrColumnAttribute->name,
|
||||
'type' => $discrColumnAttribute->type ?? 'string',
|
||||
'length' => $discrColumnAttribute->length ?? 255,
|
||||
'columnDefinition' => $discrColumnAttribute->columnDefinition,
|
||||
'enumType' => $discrColumnAttribute->enumType,
|
||||
];
|
||||
|
||||
if ($discrColumnAttribute->options) {
|
||||
$columnDef['options'] = $discrColumnAttribute->options;
|
||||
}
|
||||
|
||||
$metadata->setDiscriminatorColumn($columnDef);
|
||||
} else {
|
||||
$metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]);
|
||||
}
|
||||
|
||||
// Evaluate DiscriminatorMap attribute
|
||||
if (isset($classAttributes[Mapping\DiscriminatorMap::class])) {
|
||||
$discrMapAttribute = $classAttributes[Mapping\DiscriminatorMap::class];
|
||||
$metadata->setDiscriminatorMap($discrMapAttribute->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate DoctrineChangeTrackingPolicy attribute
|
||||
if (isset($classAttributes[Mapping\ChangeTrackingPolicy::class])) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\ChangeTrackingPolicy::class);
|
||||
}
|
||||
|
||||
$changeTrackingAttribute = $classAttributes[Mapping\ChangeTrackingPolicy::class];
|
||||
$metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' . $changeTrackingAttribute->value));
|
||||
}
|
||||
|
||||
foreach ($reflectionClass->getProperties() as $property) {
|
||||
if ($this->isRepeatedPropertyDeclaration($property, $metadata)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mapping = [];
|
||||
$mapping['fieldName'] = $property->name;
|
||||
|
||||
// Evaluate #[Cache] attribute
|
||||
$cacheAttribute = $this->reader->getPropertyAttribute($property, Mapping\Cache::class);
|
||||
if ($cacheAttribute !== null) {
|
||||
$mapping['cache'] = $metadata->getAssociationCacheDefaults(
|
||||
$mapping['fieldName'],
|
||||
[
|
||||
'usage' => (int) constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $cacheAttribute->usage),
|
||||
'region' => $cacheAttribute->region,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Check for JoinColumn/JoinColumns attributes
|
||||
$joinColumns = [];
|
||||
|
||||
$joinColumnAttributes = $this->reader->getPropertyAttributeCollection($property, Mapping\JoinColumn::class);
|
||||
|
||||
foreach ($joinColumnAttributes as $joinColumnAttribute) {
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnAttribute);
|
||||
}
|
||||
|
||||
// Field can only be attributed with one of:
|
||||
// Column, OneToOne, OneToMany, ManyToOne, ManyToMany, Embedded
|
||||
$columnAttribute = $this->reader->getPropertyAttribute($property, Mapping\Column::class);
|
||||
$oneToOneAttribute = $this->reader->getPropertyAttribute($property, Mapping\OneToOne::class);
|
||||
$oneToManyAttribute = $this->reader->getPropertyAttribute($property, Mapping\OneToMany::class);
|
||||
$manyToOneAttribute = $this->reader->getPropertyAttribute($property, Mapping\ManyToOne::class);
|
||||
$manyToManyAttribute = $this->reader->getPropertyAttribute($property, Mapping\ManyToMany::class);
|
||||
$embeddedAttribute = $this->reader->getPropertyAttribute($property, Mapping\Embedded::class);
|
||||
|
||||
if ($columnAttribute !== null) {
|
||||
$mapping = $this->columnToArray($property->name, $columnAttribute);
|
||||
|
||||
if ($this->reader->getPropertyAttribute($property, Mapping\Id::class)) {
|
||||
$mapping['id'] = true;
|
||||
}
|
||||
|
||||
$generatedValueAttribute = $this->reader->getPropertyAttribute($property, Mapping\GeneratedValue::class);
|
||||
|
||||
if ($generatedValueAttribute !== null) {
|
||||
$metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAttribute->strategy));
|
||||
}
|
||||
|
||||
if ($this->reader->getPropertyAttribute($property, Mapping\Version::class)) {
|
||||
$metadata->setVersionMapping($mapping);
|
||||
}
|
||||
|
||||
$metadata->mapField($mapping);
|
||||
|
||||
// Check for SequenceGenerator/TableGenerator definition
|
||||
$seqGeneratorAttribute = $this->reader->getPropertyAttribute($property, Mapping\SequenceGenerator::class);
|
||||
$customGeneratorAttribute = $this->reader->getPropertyAttribute($property, Mapping\CustomIdGenerator::class);
|
||||
|
||||
if ($seqGeneratorAttribute !== null) {
|
||||
$metadata->setSequenceGeneratorDefinition(
|
||||
[
|
||||
'sequenceName' => $seqGeneratorAttribute->sequenceName,
|
||||
'allocationSize' => $seqGeneratorAttribute->allocationSize,
|
||||
'initialValue' => $seqGeneratorAttribute->initialValue,
|
||||
],
|
||||
);
|
||||
} elseif ($customGeneratorAttribute !== null) {
|
||||
$metadata->setCustomGeneratorDefinition(
|
||||
[
|
||||
'class' => $customGeneratorAttribute->class,
|
||||
],
|
||||
);
|
||||
}
|
||||
} elseif ($oneToOneAttribute !== null) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\OneToOne::class);
|
||||
}
|
||||
|
||||
if ($this->reader->getPropertyAttribute($property, Mapping\Id::class)) {
|
||||
$mapping['id'] = true;
|
||||
}
|
||||
|
||||
$mapping['targetEntity'] = $oneToOneAttribute->targetEntity;
|
||||
$mapping['joinColumns'] = $joinColumns;
|
||||
$mapping['mappedBy'] = $oneToOneAttribute->mappedBy;
|
||||
$mapping['inversedBy'] = $oneToOneAttribute->inversedBy;
|
||||
$mapping['cascade'] = $oneToOneAttribute->cascade;
|
||||
$mapping['orphanRemoval'] = $oneToOneAttribute->orphanRemoval;
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $oneToOneAttribute->fetch);
|
||||
$metadata->mapOneToOne($mapping);
|
||||
} elseif ($oneToManyAttribute !== null) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\OneToMany::class);
|
||||
}
|
||||
|
||||
$mapping['mappedBy'] = $oneToManyAttribute->mappedBy;
|
||||
$mapping['targetEntity'] = $oneToManyAttribute->targetEntity;
|
||||
$mapping['cascade'] = $oneToManyAttribute->cascade;
|
||||
$mapping['indexBy'] = $oneToManyAttribute->indexBy;
|
||||
$mapping['orphanRemoval'] = $oneToManyAttribute->orphanRemoval;
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $oneToManyAttribute->fetch);
|
||||
|
||||
$orderByAttribute = $this->reader->getPropertyAttribute($property, Mapping\OrderBy::class);
|
||||
|
||||
if ($orderByAttribute !== null) {
|
||||
$mapping['orderBy'] = $orderByAttribute->value;
|
||||
}
|
||||
|
||||
$metadata->mapOneToMany($mapping);
|
||||
} elseif ($manyToOneAttribute !== null) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\ManyToOne::class);
|
||||
}
|
||||
|
||||
$idAttribute = $this->reader->getPropertyAttribute($property, Mapping\Id::class);
|
||||
|
||||
if ($idAttribute !== null) {
|
||||
$mapping['id'] = true;
|
||||
}
|
||||
|
||||
$mapping['joinColumns'] = $joinColumns;
|
||||
$mapping['cascade'] = $manyToOneAttribute->cascade;
|
||||
$mapping['inversedBy'] = $manyToOneAttribute->inversedBy;
|
||||
$mapping['targetEntity'] = $manyToOneAttribute->targetEntity;
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $manyToOneAttribute->fetch);
|
||||
$metadata->mapManyToOne($mapping);
|
||||
} elseif ($manyToManyAttribute !== null) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\ManyToMany::class);
|
||||
}
|
||||
|
||||
$joinTable = [];
|
||||
$joinTableAttribute = $this->reader->getPropertyAttribute($property, Mapping\JoinTable::class);
|
||||
|
||||
if ($joinTableAttribute !== null) {
|
||||
$joinTable = [
|
||||
'name' => $joinTableAttribute->name,
|
||||
'schema' => $joinTableAttribute->schema,
|
||||
];
|
||||
|
||||
if ($joinTableAttribute->options) {
|
||||
$joinTable['options'] = $joinTableAttribute->options;
|
||||
}
|
||||
|
||||
foreach ($joinTableAttribute->joinColumns as $joinColumn) {
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
|
||||
foreach ($joinTableAttribute->inverseJoinColumns as $joinColumn) {
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->reader->getPropertyAttributeCollection($property, Mapping\JoinColumn::class) as $joinColumn) {
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
|
||||
foreach ($this->reader->getPropertyAttributeCollection($property, Mapping\InverseJoinColumn::class) as $joinColumn) {
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
|
||||
$mapping['joinTable'] = $joinTable;
|
||||
$mapping['targetEntity'] = $manyToManyAttribute->targetEntity;
|
||||
$mapping['mappedBy'] = $manyToManyAttribute->mappedBy;
|
||||
$mapping['inversedBy'] = $manyToManyAttribute->inversedBy;
|
||||
$mapping['cascade'] = $manyToManyAttribute->cascade;
|
||||
$mapping['indexBy'] = $manyToManyAttribute->indexBy;
|
||||
$mapping['orphanRemoval'] = $manyToManyAttribute->orphanRemoval;
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $manyToManyAttribute->fetch);
|
||||
|
||||
$orderByAttribute = $this->reader->getPropertyAttribute($property, Mapping\OrderBy::class);
|
||||
|
||||
if ($orderByAttribute !== null) {
|
||||
$mapping['orderBy'] = $orderByAttribute->value;
|
||||
}
|
||||
|
||||
$metadata->mapManyToMany($mapping);
|
||||
} elseif ($embeddedAttribute !== null) {
|
||||
$mapping['class'] = $embeddedAttribute->class;
|
||||
$mapping['columnPrefix'] = $embeddedAttribute->columnPrefix;
|
||||
|
||||
$metadata->mapEmbedded($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate AssociationOverrides attribute
|
||||
if (isset($classAttributes[Mapping\AssociationOverrides::class])) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\AssociationOverride::class);
|
||||
}
|
||||
|
||||
$associationOverride = $classAttributes[Mapping\AssociationOverrides::class];
|
||||
|
||||
foreach ($associationOverride->overrides as $associationOverride) {
|
||||
$override = [];
|
||||
$fieldName = $associationOverride->name;
|
||||
|
||||
// Check for JoinColumn/JoinColumns attributes
|
||||
if ($associationOverride->joinColumns) {
|
||||
$joinColumns = [];
|
||||
|
||||
foreach ($associationOverride->joinColumns as $joinColumn) {
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
|
||||
$override['joinColumns'] = $joinColumns;
|
||||
}
|
||||
|
||||
if ($associationOverride->inverseJoinColumns) {
|
||||
$joinColumns = [];
|
||||
|
||||
foreach ($associationOverride->inverseJoinColumns as $joinColumn) {
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
|
||||
$override['inverseJoinColumns'] = $joinColumns;
|
||||
}
|
||||
|
||||
// Check for JoinTable attributes
|
||||
if ($associationOverride->joinTable) {
|
||||
$joinTableAnnot = $associationOverride->joinTable;
|
||||
$joinTable = [
|
||||
'name' => $joinTableAnnot->name,
|
||||
'schema' => $joinTableAnnot->schema,
|
||||
'joinColumns' => $override['joinColumns'] ?? [],
|
||||
'inverseJoinColumns' => $override['inverseJoinColumns'] ?? [],
|
||||
];
|
||||
|
||||
unset($override['joinColumns'], $override['inverseJoinColumns']);
|
||||
|
||||
$override['joinTable'] = $joinTable;
|
||||
}
|
||||
|
||||
// Check for inversedBy
|
||||
if ($associationOverride->inversedBy) {
|
||||
$override['inversedBy'] = $associationOverride->inversedBy;
|
||||
}
|
||||
|
||||
// Check for `fetch`
|
||||
if ($associationOverride->fetch) {
|
||||
$override['fetch'] = constant(ClassMetadata::class . '::FETCH_' . $associationOverride->fetch);
|
||||
}
|
||||
|
||||
$metadata->setAssociationOverride($fieldName, $override);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate AttributeOverrides attribute
|
||||
if (isset($classAttributes[Mapping\AttributeOverrides::class])) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\AttributeOverrides::class);
|
||||
}
|
||||
|
||||
$attributeOverridesAnnot = $classAttributes[Mapping\AttributeOverrides::class];
|
||||
|
||||
foreach ($attributeOverridesAnnot->overrides as $attributeOverride) {
|
||||
$mapping = $this->columnToArray($attributeOverride->name, $attributeOverride->column);
|
||||
|
||||
$metadata->setAttributeOverride($attributeOverride->name, $mapping);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate EntityListeners attribute
|
||||
if (isset($classAttributes[Mapping\EntityListeners::class])) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\EntityListeners::class);
|
||||
}
|
||||
|
||||
$entityListenersAttribute = $classAttributes[Mapping\EntityListeners::class];
|
||||
|
||||
foreach ($entityListenersAttribute->value as $item) {
|
||||
$listenerClassName = $metadata->fullyQualifiedClassName($item);
|
||||
|
||||
if (! class_exists($listenerClassName)) {
|
||||
throw MappingException::entityListenerClassNotFound($listenerClassName, $className);
|
||||
}
|
||||
|
||||
$hasMapping = false;
|
||||
$listenerClass = new ReflectionClass($listenerClassName);
|
||||
|
||||
foreach ($listenerClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
||||
// find method callbacks.
|
||||
$callbacks = $this->getMethodCallbacks($method);
|
||||
$hasMapping = $hasMapping ?: ! empty($callbacks);
|
||||
|
||||
foreach ($callbacks as $value) {
|
||||
$metadata->addEntityListener($value[1], $listenerClassName, $value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the listener using naming convention.
|
||||
if (! $hasMapping) {
|
||||
EntityListenerBuilder::bindEntityListener($metadata, $listenerClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate #[HasLifecycleCallbacks] attribute
|
||||
if (isset($classAttributes[Mapping\HasLifecycleCallbacks::class])) {
|
||||
if ($metadata->isEmbeddedClass) {
|
||||
throw MappingException::invalidAttributeOnEmbeddable($metadata->name, Mapping\HasLifecycleCallbacks::class);
|
||||
}
|
||||
|
||||
foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
|
||||
foreach ($this->getMethodCallbacks($method) as $value) {
|
||||
$metadata->addLifecycleCallback($value[0], $value[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve the fetch mode.
|
||||
*
|
||||
* @param class-string $className The class name.
|
||||
* @param string $fetchMode The fetch mode.
|
||||
*
|
||||
* @return ClassMetadata::FETCH_* The fetch mode as defined in ClassMetadata.
|
||||
*
|
||||
* @throws MappingException If the fetch mode is not valid.
|
||||
*/
|
||||
private function getFetchMode(string $className, string $fetchMode): int
|
||||
{
|
||||
if (! defined('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode)) {
|
||||
throw MappingException::invalidFetchMode($className, $fetchMode);
|
||||
}
|
||||
|
||||
return constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve the generated mode.
|
||||
*
|
||||
* @throws MappingException If the fetch mode is not valid.
|
||||
*/
|
||||
private function getGeneratedMode(string $generatedMode): int
|
||||
{
|
||||
if (! defined('Doctrine\ORM\Mapping\ClassMetadata::GENERATED_' . $generatedMode)) {
|
||||
throw MappingException::invalidGeneratedMode($generatedMode);
|
||||
}
|
||||
|
||||
return constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATED_' . $generatedMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given method.
|
||||
*
|
||||
* @return list<array{string, string}>
|
||||
* @phpstan-return list<array{string, (Events::*)}>
|
||||
*/
|
||||
private function getMethodCallbacks(ReflectionMethod $method): array
|
||||
{
|
||||
$callbacks = [];
|
||||
$attributes = $this->reader->getMethodAttributes($method);
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
if ($attribute instanceof Mapping\PrePersist) {
|
||||
$callbacks[] = [$method->name, Events::prePersist];
|
||||
}
|
||||
|
||||
if ($attribute instanceof Mapping\PostPersist) {
|
||||
$callbacks[] = [$method->name, Events::postPersist];
|
||||
}
|
||||
|
||||
if ($attribute instanceof Mapping\PreUpdate) {
|
||||
$callbacks[] = [$method->name, Events::preUpdate];
|
||||
}
|
||||
|
||||
if ($attribute instanceof Mapping\PostUpdate) {
|
||||
$callbacks[] = [$method->name, Events::postUpdate];
|
||||
}
|
||||
|
||||
if ($attribute instanceof Mapping\PreRemove) {
|
||||
$callbacks[] = [$method->name, Events::preRemove];
|
||||
}
|
||||
|
||||
if ($attribute instanceof Mapping\PostRemove) {
|
||||
$callbacks[] = [$method->name, Events::postRemove];
|
||||
}
|
||||
|
||||
if ($attribute instanceof Mapping\PostLoad) {
|
||||
$callbacks[] = [$method->name, Events::postLoad];
|
||||
}
|
||||
|
||||
if ($attribute instanceof Mapping\PreFlush) {
|
||||
$callbacks[] = [$method->name, Events::preFlush];
|
||||
}
|
||||
}
|
||||
|
||||
return $callbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given JoinColumn as array
|
||||
*
|
||||
* @return mixed[]
|
||||
* @phpstan-return array{
|
||||
* name: string|null,
|
||||
* unique: bool,
|
||||
* nullable: bool,
|
||||
* onDelete: mixed,
|
||||
* columnDefinition: string|null,
|
||||
* referencedColumnName: string,
|
||||
* options?: array<string, mixed>
|
||||
* }
|
||||
*/
|
||||
private function joinColumnToArray(Mapping\JoinColumn|Mapping\InverseJoinColumn $joinColumn): array
|
||||
{
|
||||
$mapping = [
|
||||
'name' => $joinColumn->name,
|
||||
'deferrable' => $joinColumn->deferrable,
|
||||
'unique' => $joinColumn->unique,
|
||||
'nullable' => $joinColumn->nullable,
|
||||
'onDelete' => $joinColumn->onDelete,
|
||||
'columnDefinition' => $joinColumn->columnDefinition,
|
||||
'referencedColumnName' => $joinColumn->referencedColumnName,
|
||||
];
|
||||
|
||||
if ($joinColumn->options) {
|
||||
$mapping['options'] = $joinColumn->options;
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given Column as array
|
||||
*
|
||||
* @return mixed[]
|
||||
* @phpstan-return array{
|
||||
* fieldName: string,
|
||||
* type: mixed,
|
||||
* scale: int,
|
||||
* length: int,
|
||||
* unique: bool,
|
||||
* nullable: bool,
|
||||
* index: bool,
|
||||
* precision: int,
|
||||
* enumType?: class-string,
|
||||
* options?: mixed[],
|
||||
* columnName?: string,
|
||||
* columnDefinition?: string
|
||||
* }
|
||||
*/
|
||||
private function columnToArray(string $fieldName, Mapping\Column $column): array
|
||||
{
|
||||
$mapping = [
|
||||
'fieldName' => $fieldName,
|
||||
'type' => $column->type,
|
||||
'scale' => $column->scale,
|
||||
'length' => $column->length,
|
||||
'unique' => $column->unique,
|
||||
'nullable' => $column->nullable,
|
||||
'index' => $column->index,
|
||||
'precision' => $column->precision,
|
||||
];
|
||||
|
||||
if ($column->options) {
|
||||
$mapping['options'] = $column->options;
|
||||
}
|
||||
|
||||
if (isset($column->name)) {
|
||||
$mapping['columnName'] = $column->name;
|
||||
}
|
||||
|
||||
if (isset($column->columnDefinition)) {
|
||||
$mapping['columnDefinition'] = $column->columnDefinition;
|
||||
}
|
||||
|
||||
if ($column->updatable === false) {
|
||||
$mapping['notUpdatable'] = true;
|
||||
}
|
||||
|
||||
if ($column->insertable === false) {
|
||||
$mapping['notInsertable'] = true;
|
||||
}
|
||||
|
||||
if ($column->generated !== null) {
|
||||
$mapping['generated'] = $this->getGeneratedMode($column->generated);
|
||||
}
|
||||
|
||||
if ($column->enumType) {
|
||||
$mapping['enumType'] = $column->enumType;
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
}
|
||||
146
backend/vendor/doctrine/orm/src/Mapping/Driver/AttributeReader.php
vendored
Normal file
146
backend/vendor/doctrine/orm/src/Mapping/Driver/AttributeReader.php
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\ORM\Mapping\MappingAttribute;
|
||||
use LogicException;
|
||||
use ReflectionAttribute;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function assert;
|
||||
use function is_string;
|
||||
use function is_subclass_of;
|
||||
use function sprintf;
|
||||
|
||||
/** @internal */
|
||||
final class AttributeReader
|
||||
{
|
||||
/** @var array<class-string<MappingAttribute>, bool> */
|
||||
private array $isRepeatableAttribute = [];
|
||||
|
||||
/**
|
||||
* @phpstan-return class-string-map<T, T|RepeatableAttributeCollection<T>>
|
||||
*
|
||||
* @template T of MappingAttribute
|
||||
*/
|
||||
public function getClassAttributes(ReflectionClass $class): array
|
||||
{
|
||||
return $this->convertToAttributeInstances($class->getAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string-map<T, T|RepeatableAttributeCollection<T>>
|
||||
*
|
||||
* @template T of MappingAttribute
|
||||
*/
|
||||
public function getMethodAttributes(ReflectionMethod $method): array
|
||||
{
|
||||
return $this->convertToAttributeInstances($method->getAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string-map<T, T|RepeatableAttributeCollection<T>>
|
||||
*
|
||||
* @template T of MappingAttribute
|
||||
*/
|
||||
public function getPropertyAttributes(ReflectionProperty $property): array
|
||||
{
|
||||
return $this->convertToAttributeInstances($property->getAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<T> $attributeName The name of the annotation.
|
||||
*
|
||||
* @return T|null
|
||||
*
|
||||
* @template T of MappingAttribute
|
||||
*/
|
||||
public function getPropertyAttribute(ReflectionProperty $property, string $attributeName)
|
||||
{
|
||||
if ($this->isRepeatable($attributeName)) {
|
||||
throw new LogicException(sprintf(
|
||||
'The attribute "%s" is repeatable. Call getPropertyAttributeCollection() instead.',
|
||||
$attributeName,
|
||||
));
|
||||
}
|
||||
|
||||
return $this->getPropertyAttributes($property)[$attributeName] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<T> $attributeName The name of the annotation.
|
||||
*
|
||||
* @return RepeatableAttributeCollection<T>
|
||||
*
|
||||
* @template T of MappingAttribute
|
||||
*/
|
||||
public function getPropertyAttributeCollection(
|
||||
ReflectionProperty $property,
|
||||
string $attributeName,
|
||||
): RepeatableAttributeCollection {
|
||||
if (! $this->isRepeatable($attributeName)) {
|
||||
throw new LogicException(sprintf(
|
||||
'The attribute "%s" is not repeatable. Call getPropertyAttribute() instead.',
|
||||
$attributeName,
|
||||
));
|
||||
}
|
||||
|
||||
return $this->getPropertyAttributes($property)[$attributeName] ?? new RepeatableAttributeCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<ReflectionAttribute> $attributes
|
||||
*
|
||||
* @return class-string-map<T, T|RepeatableAttributeCollection<T>>
|
||||
*
|
||||
* @template T of MappingAttribute
|
||||
*/
|
||||
private function convertToAttributeInstances(array $attributes): array
|
||||
{
|
||||
$instances = [];
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
$attributeName = $attribute->getName();
|
||||
assert(is_string($attributeName));
|
||||
// Make sure we only get Doctrine Attributes
|
||||
if (! is_subclass_of($attributeName, MappingAttribute::class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$instance = $attribute->newInstance();
|
||||
assert($instance instanceof MappingAttribute);
|
||||
|
||||
if ($this->isRepeatable($attributeName)) {
|
||||
if (! isset($instances[$attributeName])) {
|
||||
$instances[$attributeName] = new RepeatableAttributeCollection();
|
||||
}
|
||||
|
||||
$collection = $instances[$attributeName];
|
||||
assert($collection instanceof RepeatableAttributeCollection);
|
||||
$collection[] = $instance;
|
||||
} else {
|
||||
$instances[$attributeName] = $instance;
|
||||
}
|
||||
}
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/** @param class-string<MappingAttribute> $attributeClassName */
|
||||
private function isRepeatable(string $attributeClassName): bool
|
||||
{
|
||||
if (isset($this->isRepeatableAttribute[$attributeClassName])) {
|
||||
return $this->isRepeatableAttribute[$attributeClassName];
|
||||
}
|
||||
|
||||
$reflectionClass = new ReflectionClass($attributeClassName);
|
||||
$attribute = $reflectionClass->getAttributes()[0]->newInstance();
|
||||
|
||||
return $this->isRepeatableAttribute[$attributeClassName] = ($attribute->flags & Attribute::IS_REPEATABLE) > 0;
|
||||
}
|
||||
}
|
||||
639
backend/vendor/doctrine/orm/src/Mapping/Driver/DatabaseDriver.php
vendored
Normal file
639
backend/vendor/doctrine/orm/src/Mapping/Driver/DatabaseDriver.php
vendored
Normal file
@@ -0,0 +1,639 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\DBAL\Schema\AbstractAsset;
|
||||
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||
use Doctrine\DBAL\Schema\Column;
|
||||
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\Index;
|
||||
use Doctrine\DBAL\Schema\Index\IndexedColumn;
|
||||
use Doctrine\DBAL\Schema\Index\IndexType;
|
||||
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
|
||||
use Doctrine\DBAL\Schema\NamedObject;
|
||||
use Doctrine\DBAL\Schema\PrimaryKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\SchemaException;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\Inflector\Inflector;
|
||||
use Doctrine\Inflector\InflectorFactory;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata as PersistenceClassMetadata;
|
||||
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
|
||||
use InvalidArgumentException;
|
||||
use TypeError;
|
||||
|
||||
use function array_diff;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function current;
|
||||
use function enum_exists;
|
||||
use function get_debug_type;
|
||||
use function in_array;
|
||||
use function method_exists;
|
||||
use function preg_replace;
|
||||
use function sort;
|
||||
use function sprintf;
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
* The DatabaseDriver reverse engineers the mapping metadata from a database.
|
||||
*
|
||||
* @deprecated No replacement planned
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
*/
|
||||
class DatabaseDriver implements MappingDriver
|
||||
{
|
||||
/**
|
||||
* Replacement for {@see Types::ARRAY}.
|
||||
*
|
||||
* To be removed as soon as support for DBAL 3 is dropped.
|
||||
*/
|
||||
private const ARRAY = 'array';
|
||||
|
||||
/**
|
||||
* Replacement for {@see Types::OBJECT}.
|
||||
*
|
||||
* To be removed as soon as support for DBAL 3 is dropped.
|
||||
*/
|
||||
private const OBJECT = 'object';
|
||||
|
||||
/** @var array<string,Table>|null */
|
||||
private array|null $tables = null;
|
||||
|
||||
/** @var array<class-string, string> */
|
||||
private array $classToTableNames = [];
|
||||
|
||||
/** @phpstan-var array<string, Table> */
|
||||
private array $manyToManyTables = [];
|
||||
|
||||
/** @var mixed[] */
|
||||
private array $classNamesForTables = [];
|
||||
|
||||
/** @var mixed[] */
|
||||
private array $fieldNamesForColumns = [];
|
||||
|
||||
/**
|
||||
* The namespace for the generated entities.
|
||||
*/
|
||||
private string|null $namespace = null;
|
||||
|
||||
private Inflector $inflector;
|
||||
|
||||
public function __construct(private readonly AbstractSchemaManager $sm)
|
||||
{
|
||||
$this->inflector = InflectorFactory::create()->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the namespace for the generated entities.
|
||||
*/
|
||||
public function setNamespace(string $namespace): void
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
public function isTransient(string $className): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getAllClassNames(): array
|
||||
{
|
||||
$this->reverseEngineerMappingFromDatabase();
|
||||
|
||||
return array_keys($this->classToTableNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets class name for a table.
|
||||
*/
|
||||
public function setClassNameForTable(string $tableName, string $className): void
|
||||
{
|
||||
$this->classNamesForTables[$tableName] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets field name for a column on a specific table.
|
||||
*/
|
||||
public function setFieldNameForColumn(string $tableName, string $columnName, string $fieldName): void
|
||||
{
|
||||
$this->fieldNamesForColumns[$tableName][$columnName] = $fieldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets tables manually instead of relying on the reverse engineering capabilities of SchemaManager.
|
||||
*
|
||||
* @param Table[] $entityTables
|
||||
* @param Table[] $manyToManyTables
|
||||
* @phpstan-param list<Table> $entityTables
|
||||
* @phpstan-param list<Table> $manyToManyTables
|
||||
*/
|
||||
public function setTables(array $entityTables, array $manyToManyTables): void
|
||||
{
|
||||
$this->tables = $this->manyToManyTables = $this->classToTableNames = [];
|
||||
|
||||
foreach ($entityTables as $table) {
|
||||
$className = $this->getClassNameForTable(self::getAssetName($table));
|
||||
|
||||
$this->classToTableNames[$className] = self::getAssetName($table);
|
||||
$this->tables[self::getAssetName($table)] = $table;
|
||||
}
|
||||
|
||||
foreach ($manyToManyTables as $table) {
|
||||
$this->manyToManyTables[self::getAssetName($table)] = $table;
|
||||
}
|
||||
}
|
||||
|
||||
public function setInflector(Inflector $inflector): void
|
||||
{
|
||||
$this->inflector = $inflector;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param class-string<T> $className
|
||||
* @param ClassMetadata<T> $metadata
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function loadMetadataForClass(string $className, PersistenceClassMetadata $metadata): void
|
||||
{
|
||||
if (! $metadata instanceof ClassMetadata) {
|
||||
throw new TypeError(sprintf(
|
||||
'Argument #2 passed to %s() must be an instance of %s, %s given.',
|
||||
__METHOD__,
|
||||
ClassMetadata::class,
|
||||
get_debug_type($metadata),
|
||||
));
|
||||
}
|
||||
|
||||
$this->reverseEngineerMappingFromDatabase();
|
||||
|
||||
if (! isset($this->classToTableNames[$className])) {
|
||||
throw new InvalidArgumentException('Unknown class ' . $className);
|
||||
}
|
||||
|
||||
$tableName = $this->classToTableNames[$className];
|
||||
|
||||
$metadata->name = $className;
|
||||
$metadata->table['name'] = $tableName;
|
||||
|
||||
$this->buildIndexes($metadata);
|
||||
$this->buildFieldMappings($metadata);
|
||||
$this->buildToOneAssociationMappings($metadata);
|
||||
|
||||
foreach ($this->manyToManyTables as $manyTable) {
|
||||
foreach ($manyTable->getForeignKeys() as $foreignKey) {
|
||||
// foreign key maps to the table of the current entity, many to many association probably exists
|
||||
if (! (strtolower($tableName) === strtolower(self::getReferencedTableName($foreignKey)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$myFk = $foreignKey;
|
||||
$otherFk = null;
|
||||
|
||||
foreach ($manyTable->getForeignKeys() as $foreignKey) {
|
||||
if ($foreignKey !== $myFk) {
|
||||
$otherFk = $foreignKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $otherFk) {
|
||||
// the definition of this many to many table does not contain
|
||||
// enough foreign key information to continue reverse engineering.
|
||||
continue;
|
||||
}
|
||||
|
||||
$localColumn = current(self::getReferencingColumnNames($myFk));
|
||||
|
||||
$associationMapping = [];
|
||||
$associationMapping['fieldName'] = $this->getFieldNameForColumn(self::getAssetName($manyTable), current(self::getReferencingColumnNames($otherFk)), true);
|
||||
$associationMapping['targetEntity'] = $this->getClassNameForTable(self::getReferencedTableName($otherFk));
|
||||
|
||||
if (self::getAssetName(current($manyTable->getColumns())) === $localColumn) {
|
||||
$associationMapping['inversedBy'] = $this->getFieldNameForColumn(self::getAssetName($manyTable), current(self::getReferencingColumnNames($myFk)), true);
|
||||
$associationMapping['joinTable'] = [
|
||||
'name' => strtolower(self::getAssetName($manyTable)),
|
||||
'joinColumns' => [],
|
||||
'inverseJoinColumns' => [],
|
||||
];
|
||||
|
||||
$fkCols = self::getReferencedColumnNames($myFk);
|
||||
$cols = self::getReferencingColumnNames($myFk);
|
||||
|
||||
for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) {
|
||||
$associationMapping['joinTable']['joinColumns'][] = [
|
||||
'name' => $cols[$i],
|
||||
'referencedColumnName' => $fkCols[$i],
|
||||
];
|
||||
}
|
||||
|
||||
$fkCols = self::getReferencedColumnNames($otherFk);
|
||||
$cols = self::getReferencingColumnNames($otherFk);
|
||||
|
||||
for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) {
|
||||
$associationMapping['joinTable']['inverseJoinColumns'][] = [
|
||||
'name' => $cols[$i],
|
||||
'referencedColumnName' => $fkCols[$i],
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$associationMapping['mappedBy'] = $this->getFieldNameForColumn(
|
||||
// @phpstan-ignore function.alreadyNarrowedType (DBAL 3 compatibility)
|
||||
method_exists(Table::class, 'getObjectName')
|
||||
? $manyTable->getObjectName()->toString()
|
||||
: $manyTable->getName(), // DBAL < 4.4
|
||||
current(self::getReferencingColumnNames($myFk)),
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
$metadata->mapManyToMany($associationMapping);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @throws MappingException */
|
||||
private function reverseEngineerMappingFromDatabase(): void
|
||||
{
|
||||
if ($this->tables !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->tables = $this->manyToManyTables = $this->classToTableNames = [];
|
||||
|
||||
foreach ($this->sm->listTables() as $table) {
|
||||
$tableName = self::getAssetName($table);
|
||||
$foreignKeys = $table->getForeignKeys();
|
||||
|
||||
$allForeignKeyColumns = [];
|
||||
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
$allForeignKeyColumns = array_merge($allForeignKeyColumns, self::getReferencingColumnNames($foreignKey));
|
||||
}
|
||||
|
||||
if (method_exists($table, 'getPrimaryKeyConstraint')) {
|
||||
$primaryKey = $table->getPrimaryKeyConstraint();
|
||||
} else {
|
||||
$primaryKey = $table->getPrimaryKey();
|
||||
}
|
||||
|
||||
if ($primaryKey === null) {
|
||||
throw new MappingException(
|
||||
'Table ' . $tableName . ' has no primary key. Doctrine does not ' .
|
||||
"support reverse engineering from tables that don't have a primary key.",
|
||||
);
|
||||
}
|
||||
|
||||
if ($primaryKey instanceof PrimaryKeyConstraint) {
|
||||
$pkColumns = array_map(static fn (UnqualifiedName $name) => $name->toString(), $primaryKey->getColumnNames());
|
||||
} else {
|
||||
$pkColumns = self::getIndexedColumns($primaryKey);
|
||||
}
|
||||
|
||||
sort($pkColumns);
|
||||
sort($allForeignKeyColumns);
|
||||
|
||||
if ($pkColumns === $allForeignKeyColumns && count($foreignKeys) === 2) {
|
||||
$this->manyToManyTables[$tableName] = $table;
|
||||
} else {
|
||||
// lower-casing is necessary because of Oracle Uppercase Tablenames,
|
||||
// assumption is lower-case + underscore separated.
|
||||
$className = $this->getClassNameForTable($tableName);
|
||||
|
||||
$this->tables[$tableName] = $table;
|
||||
$this->classToTableNames[$className] = $tableName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build indexes from a class metadata.
|
||||
*/
|
||||
private function buildIndexes(ClassMetadata $metadata): void
|
||||
{
|
||||
$tableName = $metadata->table['name'];
|
||||
$table = $this->tables[$tableName];
|
||||
$primaryKey = self::getPrimaryKey($table);
|
||||
$indexes = $table->getIndexes();
|
||||
|
||||
foreach ($indexes as $index) {
|
||||
if ($index === $primaryKey) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enum_exists(IndexType::class) && method_exists($index, 'getType')) {
|
||||
$isUnique = $index->getType() === IndexType::UNIQUE;
|
||||
} else {
|
||||
$isUnique = $index->isUnique();
|
||||
}
|
||||
|
||||
$indexName = self::getAssetName($index);
|
||||
$indexColumns = self::getIndexedColumns($index);
|
||||
$constraintType = $isUnique
|
||||
? 'uniqueConstraints'
|
||||
: 'indexes';
|
||||
|
||||
$metadata->table[$constraintType][$indexName]['columns'] = $indexColumns;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build field mapping from class metadata.
|
||||
*/
|
||||
private function buildFieldMappings(ClassMetadata $metadata): void
|
||||
{
|
||||
$tableName = $metadata->table['name'];
|
||||
$columns = $this->tables[$tableName]->getColumns();
|
||||
$primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]);
|
||||
$foreignKeys = $this->tables[$tableName]->getForeignKeys();
|
||||
$allForeignKeys = [];
|
||||
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
$allForeignKeys = array_merge($allForeignKeys, self::getReferencingColumnNames($foreignKey));
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
$fieldMappings = [];
|
||||
|
||||
foreach ($columns as $column) {
|
||||
if (in_array(self::getAssetName($column), $allForeignKeys, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fieldMapping = $this->buildFieldMapping($tableName, $column);
|
||||
|
||||
if ($primaryKeys && in_array(self::getAssetName($column), $primaryKeys, true)) {
|
||||
$fieldMapping['id'] = true;
|
||||
$ids[] = $fieldMapping;
|
||||
}
|
||||
|
||||
$fieldMappings[] = $fieldMapping;
|
||||
}
|
||||
|
||||
// We need to check for the columns here, because we might have associations as id as well.
|
||||
if ($ids && count($primaryKeys) === 1) {
|
||||
$metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO);
|
||||
}
|
||||
|
||||
foreach ($fieldMappings as $fieldMapping) {
|
||||
$metadata->mapField($fieldMapping);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build field mapping from a schema column definition
|
||||
*
|
||||
* @return mixed[]
|
||||
* @phpstan-return array{
|
||||
* fieldName: string,
|
||||
* columnName: string,
|
||||
* type: string,
|
||||
* nullable: bool,
|
||||
* options: array{
|
||||
* unsigned?: bool,
|
||||
* fixed?: bool,
|
||||
* comment: string|null,
|
||||
* default?: mixed
|
||||
* },
|
||||
* precision?: int,
|
||||
* scale?: int,
|
||||
* length?: int|null
|
||||
* }
|
||||
*/
|
||||
private function buildFieldMapping(string $tableName, Column $column): array
|
||||
{
|
||||
$fieldMapping = [
|
||||
'fieldName' => $this->getFieldNameForColumn($tableName, self::getAssetName($column), false),
|
||||
'columnName' => self::getAssetName($column),
|
||||
'type' => Type::getTypeRegistry()->lookupName($column->getType()),
|
||||
'nullable' => ! $column->getNotnull(),
|
||||
'options' => [
|
||||
'comment' => $column->getComment(),
|
||||
],
|
||||
];
|
||||
|
||||
// Type specific elements
|
||||
switch ($fieldMapping['type']) {
|
||||
case self::ARRAY:
|
||||
case Types::BLOB:
|
||||
case Types::GUID:
|
||||
case self::OBJECT:
|
||||
case Types::SIMPLE_ARRAY:
|
||||
case Types::STRING:
|
||||
case Types::TEXT:
|
||||
$fieldMapping['length'] = $column->getLength();
|
||||
$fieldMapping['options']['fixed'] = $column->getFixed();
|
||||
break;
|
||||
|
||||
case Types::DECIMAL:
|
||||
case Types::FLOAT:
|
||||
$fieldMapping['precision'] = $column->getPrecision();
|
||||
$fieldMapping['scale'] = $column->getScale();
|
||||
break;
|
||||
|
||||
case Types::INTEGER:
|
||||
case Types::BIGINT:
|
||||
case Types::SMALLINT:
|
||||
$fieldMapping['options']['unsigned'] = $column->getUnsigned();
|
||||
break;
|
||||
}
|
||||
|
||||
// Default
|
||||
$default = $column->getDefault();
|
||||
if ($default !== null) {
|
||||
$fieldMapping['options']['default'] = $default;
|
||||
}
|
||||
|
||||
return $fieldMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build to one (one to one, many to one) association mapping from class metadata.
|
||||
*/
|
||||
private function buildToOneAssociationMappings(ClassMetadata $metadata): void
|
||||
{
|
||||
assert($this->tables !== null);
|
||||
|
||||
$tableName = $metadata->table['name'];
|
||||
$primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]);
|
||||
$foreignKeys = $this->tables[$tableName]->getForeignKeys();
|
||||
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
$foreignTableName = self::getReferencedTableName($foreignKey);
|
||||
$fkColumns = self::getReferencingColumnNames($foreignKey);
|
||||
$fkForeignColumns = self::getReferencedColumnNames($foreignKey);
|
||||
$localColumn = current($fkColumns);
|
||||
$associationMapping = [
|
||||
'fieldName' => $this->getFieldNameForColumn($tableName, $localColumn, true),
|
||||
'targetEntity' => $this->getClassNameForTable($foreignTableName),
|
||||
];
|
||||
|
||||
if (isset($metadata->fieldMappings[$associationMapping['fieldName']])) {
|
||||
$associationMapping['fieldName'] .= '2'; // "foo" => "foo2"
|
||||
}
|
||||
|
||||
if ($primaryKeys && in_array($localColumn, $primaryKeys, true)) {
|
||||
$associationMapping['id'] = true;
|
||||
}
|
||||
|
||||
for ($i = 0, $fkColumnsCount = count($fkColumns); $i < $fkColumnsCount; $i++) {
|
||||
$associationMapping['joinColumns'][] = [
|
||||
'name' => $fkColumns[$i],
|
||||
'referencedColumnName' => $fkForeignColumns[$i],
|
||||
];
|
||||
}
|
||||
|
||||
// Here we need to check if $fkColumns are the same as $primaryKeys
|
||||
if (! array_diff($fkColumns, $primaryKeys)) {
|
||||
$metadata->mapOneToOne($associationMapping);
|
||||
} else {
|
||||
$metadata->mapManyToOne($associationMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve schema table definition primary keys.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function getTablePrimaryKeys(Table $table): array
|
||||
{
|
||||
try {
|
||||
if (method_exists($table, 'getPrimaryKeyConstraint')) {
|
||||
return array_map(static fn (UnqualifiedName $name) => $name->toString(), $table->getPrimaryKeyConstraint()->getColumnNames());
|
||||
}
|
||||
|
||||
return self::getIndexedColumns($table->getPrimaryKey());
|
||||
} catch (SchemaException) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapped class name for a table if it exists. Otherwise return "classified" version.
|
||||
*
|
||||
* @return class-string
|
||||
*/
|
||||
private function getClassNameForTable(string $tableName): string
|
||||
{
|
||||
if (isset($this->classNamesForTables[$tableName])) {
|
||||
return $this->namespace . $this->classNamesForTables[$tableName];
|
||||
}
|
||||
|
||||
return $this->namespace . $this->inflector->classify(strtolower($tableName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mapped field name for a column, if it exists. Otherwise return camelized version.
|
||||
*
|
||||
* @param bool $fk Whether the column is a foreignkey or not.
|
||||
*/
|
||||
private function getFieldNameForColumn(
|
||||
string $tableName,
|
||||
string $columnName,
|
||||
bool $fk = false,
|
||||
): string {
|
||||
if (isset($this->fieldNamesForColumns[$tableName], $this->fieldNamesForColumns[$tableName][$columnName])) {
|
||||
return $this->fieldNamesForColumns[$tableName][$columnName];
|
||||
}
|
||||
|
||||
$columnName = strtolower($columnName);
|
||||
|
||||
// Replace _id if it is a foreignkey column
|
||||
if ($fk) {
|
||||
$columnName = preg_replace('/_id$/', '', $columnName);
|
||||
}
|
||||
|
||||
return $this->inflector->camelize($columnName);
|
||||
}
|
||||
|
||||
private static function getReferencedTableName(ForeignKeyConstraint $foreignKey): string
|
||||
{
|
||||
if (method_exists(ForeignKeyConstraint::class, 'getReferencedTableName')) {
|
||||
return $foreignKey->getReferencedTableName()->toString();
|
||||
}
|
||||
|
||||
return $foreignKey->getForeignTableName();
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private static function getReferencingColumnNames(ForeignKeyConstraint $foreignKey): array
|
||||
{
|
||||
if (method_exists(ForeignKeyConstraint::class, 'getReferencingColumnNames')) {
|
||||
return array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencingColumnNames());
|
||||
}
|
||||
|
||||
return $foreignKey->getLocalColumns();
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private static function getReferencedColumnNames(ForeignKeyConstraint $foreignKey): array
|
||||
{
|
||||
if (method_exists(ForeignKeyConstraint::class, 'getReferencedColumnNames')) {
|
||||
return array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencedColumnNames());
|
||||
}
|
||||
|
||||
return $foreignKey->getForeignColumns();
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private static function getIndexedColumns(Index $index): array
|
||||
{
|
||||
if (method_exists(Index::class, 'getIndexedColumns')) {
|
||||
return array_map(static fn (IndexedColumn $indexedColumn) => $indexedColumn->getColumnName()->toString(), $index->getIndexedColumns());
|
||||
}
|
||||
|
||||
return $index->getColumns();
|
||||
}
|
||||
|
||||
private static function getPrimaryKey(Table $table): Index|null
|
||||
{
|
||||
$primaryKeyConstraint = null;
|
||||
|
||||
if (method_exists(Table::class, 'getPrimaryKeyConstraint')) {
|
||||
$primaryKeyConstraint = $table->getPrimaryKeyConstraint();
|
||||
}
|
||||
|
||||
foreach ($table->getIndexes() as $index) {
|
||||
if ($primaryKeyConstraint !== null) {
|
||||
$primaryKeyConstraintColumns = array_map(static fn (UnqualifiedName $name) => $name->toString(), $primaryKeyConstraint->getColumnNames());
|
||||
|
||||
if ($primaryKeyConstraintColumns === self::getIndexedColumns($index)) {
|
||||
return $index;
|
||||
}
|
||||
} elseif ($index->isPrimary()) {
|
||||
return $index;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static function getAssetName(AbstractAsset $asset): string
|
||||
{
|
||||
return $asset instanceof NamedObject
|
||||
? $asset->getObjectName()->toString()
|
||||
// DBAL < 4.4
|
||||
: $asset->getName();
|
||||
}
|
||||
}
|
||||
35
backend/vendor/doctrine/orm/src/Mapping/Driver/LoadMappingFileImplementation.php
vendored
Normal file
35
backend/vendor/doctrine/orm/src/Mapping/Driver/LoadMappingFileImplementation.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\StaticReflectionService;
|
||||
|
||||
use function class_exists;
|
||||
|
||||
if (! class_exists(StaticReflectionService::class)) {
|
||||
/** @internal */
|
||||
trait LoadMappingFileImplementation
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function loadMappingFile($file): array
|
||||
{
|
||||
return $this->doLoadMappingFile($file);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/** @internal */
|
||||
trait LoadMappingFileImplementation
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function loadMappingFile($file)
|
||||
{
|
||||
return $this->doLoadMappingFile($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
backend/vendor/doctrine/orm/src/Mapping/Driver/ReflectionBasedDriver.php
vendored
Normal file
44
backend/vendor/doctrine/orm/src/Mapping/Driver/ReflectionBasedDriver.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use ReflectionProperty;
|
||||
|
||||
/** @internal */
|
||||
trait ReflectionBasedDriver
|
||||
{
|
||||
/**
|
||||
* Helps to deal with the case that reflection may report properties inherited from parent classes.
|
||||
* When we know about the fields already (inheritance has been anticipated in ClassMetadataFactory),
|
||||
* the driver must skip them.
|
||||
*
|
||||
* The declaring classes may mismatch when there are private properties: The same property name may be
|
||||
* reported multiple times, but since it is private, it is in fact multiple (different) properties in
|
||||
* different classes. In that case, report the property as an individual field. (ClassMetadataFactory will
|
||||
* probably fail in that case, though.)
|
||||
*/
|
||||
private function isRepeatedPropertyDeclaration(ReflectionProperty $property, ClassMetadata $metadata): bool
|
||||
{
|
||||
$declaringClass = $property->class;
|
||||
|
||||
if (
|
||||
isset($metadata->fieldMappings[$property->name]->declared)
|
||||
&& $metadata->fieldMappings[$property->name]->declared === $declaringClass
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
isset($metadata->associationMappings[$property->name]->declared)
|
||||
&& $metadata->associationMappings[$property->name]->declared === $declaringClass
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isset($metadata->embeddedClasses[$property->name]->declared)
|
||||
&& $metadata->embeddedClasses[$property->name]->declared === $declaringClass;
|
||||
}
|
||||
}
|
||||
16
backend/vendor/doctrine/orm/src/Mapping/Driver/RepeatableAttributeCollection.php
vendored
Normal file
16
backend/vendor/doctrine/orm/src/Mapping/Driver/RepeatableAttributeCollection.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use ArrayObject;
|
||||
use Doctrine\ORM\Mapping\MappingAttribute;
|
||||
|
||||
/**
|
||||
* @template-extends ArrayObject<int, T>
|
||||
* @template T of MappingAttribute
|
||||
*/
|
||||
final class RepeatableAttributeCollection extends ArrayObject
|
||||
{
|
||||
}
|
||||
25
backend/vendor/doctrine/orm/src/Mapping/Driver/SimplifiedXmlDriver.php
vendored
Normal file
25
backend/vendor/doctrine/orm/src/Mapping/Driver/SimplifiedXmlDriver.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\Driver\SymfonyFileLocator;
|
||||
|
||||
/**
|
||||
* XmlDriver that additionally looks for mapping information in a global file.
|
||||
*/
|
||||
class SimplifiedXmlDriver extends XmlDriver
|
||||
{
|
||||
public const DEFAULT_FILE_EXTENSION = '.orm.xml';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function __construct($prefixes, $fileExtension = self::DEFAULT_FILE_EXTENSION, bool $isXsdValidationEnabled = true)
|
||||
{
|
||||
$locator = new SymfonyFileLocator((array) $prefixes, $fileExtension);
|
||||
|
||||
parent::__construct($locator, $fileExtension, $isXsdValidationEnabled);
|
||||
}
|
||||
}
|
||||
978
backend/vendor/doctrine/orm/src/Mapping/Driver/XmlDriver.php
vendored
Normal file
978
backend/vendor/doctrine/orm/src/Mapping/Driver/XmlDriver.php
vendored
Normal file
@@ -0,0 +1,978 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata as PersistenceClassMetadata;
|
||||
use Doctrine\Persistence\Mapping\Driver\FileDriver;
|
||||
use Doctrine\Persistence\Mapping\Driver\FileLocator;
|
||||
use DOMDocument;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use SimpleXMLElement;
|
||||
|
||||
use function assert;
|
||||
use function class_exists;
|
||||
use function constant;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function explode;
|
||||
use function extension_loaded;
|
||||
use function file_get_contents;
|
||||
use function in_array;
|
||||
use function libxml_clear_errors;
|
||||
use function libxml_get_errors;
|
||||
use function libxml_use_internal_errors;
|
||||
use function simplexml_load_string;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function strtoupper;
|
||||
|
||||
/**
|
||||
* XmlDriver is a metadata driver that enables mapping through XML files.
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
*
|
||||
* @template-extends FileDriver<SimpleXMLElement>
|
||||
*/
|
||||
class XmlDriver extends FileDriver
|
||||
{
|
||||
use LoadMappingFileImplementation;
|
||||
|
||||
public const DEFAULT_FILE_EXTENSION = '.dcm.xml';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function __construct(
|
||||
string|array|FileLocator $locator,
|
||||
string $fileExtension = self::DEFAULT_FILE_EXTENSION,
|
||||
private readonly bool $isXsdValidationEnabled = true,
|
||||
) {
|
||||
if (! extension_loaded('simplexml')) {
|
||||
throw new LogicException(
|
||||
'The XML metadata driver cannot be enabled because the SimpleXML PHP extension is missing.'
|
||||
. ' Please configure PHP with SimpleXML or choose a different metadata driver.',
|
||||
);
|
||||
}
|
||||
|
||||
if ($isXsdValidationEnabled && ! extension_loaded('dom')) {
|
||||
throw new LogicException(
|
||||
'XSD validation cannot be enabled because the DOM extension is missing.',
|
||||
);
|
||||
}
|
||||
|
||||
parent::__construct($locator, $fileExtension);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param class-string<T> $className
|
||||
* @param ClassMetadata<T> $metadata
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function loadMetadataForClass($className, PersistenceClassMetadata $metadata): void
|
||||
{
|
||||
$xmlRoot = $this->getElement($className);
|
||||
|
||||
if ($xmlRoot->getName() === 'entity') {
|
||||
if (isset($xmlRoot['repository-class'])) {
|
||||
$metadata->setCustomRepositoryClass((string) $xmlRoot['repository-class']);
|
||||
}
|
||||
|
||||
if (isset($xmlRoot['read-only']) && $this->evaluateBoolean($xmlRoot['read-only'])) {
|
||||
$metadata->markReadOnly();
|
||||
}
|
||||
} elseif ($xmlRoot->getName() === 'mapped-superclass') {
|
||||
$metadata->setCustomRepositoryClass(
|
||||
isset($xmlRoot['repository-class']) ? (string) $xmlRoot['repository-class'] : null,
|
||||
);
|
||||
$metadata->isMappedSuperclass = true;
|
||||
} elseif ($xmlRoot->getName() === 'embeddable') {
|
||||
$metadata->isEmbeddedClass = true;
|
||||
} else {
|
||||
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
||||
}
|
||||
|
||||
// Evaluate <entity...> attributes
|
||||
$primaryTable = [];
|
||||
|
||||
if (isset($xmlRoot['table'])) {
|
||||
$primaryTable['name'] = (string) $xmlRoot['table'];
|
||||
}
|
||||
|
||||
if (isset($xmlRoot['schema'])) {
|
||||
$primaryTable['schema'] = (string) $xmlRoot['schema'];
|
||||
}
|
||||
|
||||
$metadata->setPrimaryTable($primaryTable);
|
||||
|
||||
// Evaluate second level cache
|
||||
if (isset($xmlRoot->cache)) {
|
||||
$metadata->enableCache($this->cacheToArray($xmlRoot->cache));
|
||||
}
|
||||
|
||||
if (isset($xmlRoot['inheritance-type'])) {
|
||||
$inheritanceType = (string) $xmlRoot['inheritance-type'];
|
||||
$metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceType));
|
||||
|
||||
if ($metadata->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||
// Evaluate <discriminator-column...>
|
||||
if (isset($xmlRoot->{'discriminator-column'})) {
|
||||
$discrColumn = $xmlRoot->{'discriminator-column'};
|
||||
$columnDef = [
|
||||
'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null,
|
||||
'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string',
|
||||
'length' => isset($discrColumn['length']) ? (int) $discrColumn['length'] : 255,
|
||||
'columnDefinition' => isset($discrColumn['column-definition']) ? (string) $discrColumn['column-definition'] : null,
|
||||
'enumType' => isset($discrColumn['enum-type']) ? (string) $discrColumn['enum-type'] : null,
|
||||
];
|
||||
|
||||
if (isset($discrColumn['options'])) {
|
||||
$columnDef['options'] = $this->parseOptions($discrColumn['options']->children());
|
||||
}
|
||||
|
||||
$metadata->setDiscriminatorColumn($columnDef);
|
||||
} else {
|
||||
$metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]);
|
||||
}
|
||||
|
||||
// Evaluate <discriminator-map...>
|
||||
if (isset($xmlRoot->{'discriminator-map'})) {
|
||||
$map = [];
|
||||
assert($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} instanceof SimpleXMLElement);
|
||||
foreach ($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} as $discrMapElement) {
|
||||
$map[(string) $discrMapElement['value']] = (string) $discrMapElement['class'];
|
||||
}
|
||||
|
||||
$metadata->setDiscriminatorMap($map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate <change-tracking-policy...>
|
||||
if (isset($xmlRoot['change-tracking-policy'])) {
|
||||
$metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_'
|
||||
. strtoupper((string) $xmlRoot['change-tracking-policy'])));
|
||||
}
|
||||
|
||||
// Evaluate <indexes...>
|
||||
if (isset($xmlRoot->indexes)) {
|
||||
$metadata->table['indexes'] = [];
|
||||
foreach ($xmlRoot->indexes->index ?? [] as $indexXml) {
|
||||
$index = [];
|
||||
|
||||
if (isset($indexXml['columns']) && ! empty($indexXml['columns'])) {
|
||||
$index['columns'] = explode(',', (string) $indexXml['columns']);
|
||||
}
|
||||
|
||||
if (isset($indexXml['fields'])) {
|
||||
$index['fields'] = explode(',', (string) $indexXml['fields']);
|
||||
}
|
||||
|
||||
if (
|
||||
isset($index['columns'], $index['fields'])
|
||||
|| (
|
||||
! isset($index['columns'])
|
||||
&& ! isset($index['fields'])
|
||||
)
|
||||
) {
|
||||
throw MappingException::invalidIndexConfiguration(
|
||||
$className,
|
||||
(string) ($indexXml['name'] ?? count($metadata->table['indexes'])),
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($indexXml['flags'])) {
|
||||
$index['flags'] = explode(',', (string) $indexXml['flags']);
|
||||
}
|
||||
|
||||
if (isset($indexXml->options)) {
|
||||
$index['options'] = $this->parseOptions($indexXml->options->children());
|
||||
}
|
||||
|
||||
if (isset($indexXml['name'])) {
|
||||
$metadata->table['indexes'][(string) $indexXml['name']] = $index;
|
||||
} else {
|
||||
$metadata->table['indexes'][] = $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate <unique-constraints..>
|
||||
if (isset($xmlRoot->{'unique-constraints'})) {
|
||||
$metadata->table['uniqueConstraints'] = [];
|
||||
foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} ?? [] as $uniqueXml) {
|
||||
$unique = [];
|
||||
|
||||
if (isset($uniqueXml['columns']) && ! empty($uniqueXml['columns'])) {
|
||||
$unique['columns'] = explode(',', (string) $uniqueXml['columns']);
|
||||
}
|
||||
|
||||
if (isset($uniqueXml['fields'])) {
|
||||
$unique['fields'] = explode(',', (string) $uniqueXml['fields']);
|
||||
}
|
||||
|
||||
if (
|
||||
isset($unique['columns'], $unique['fields'])
|
||||
|| (
|
||||
! isset($unique['columns'])
|
||||
&& ! isset($unique['fields'])
|
||||
)
|
||||
) {
|
||||
throw MappingException::invalidUniqueConstraintConfiguration(
|
||||
$className,
|
||||
(string) ($uniqueXml['name'] ?? count($metadata->table['uniqueConstraints'])),
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($uniqueXml->options)) {
|
||||
$unique['options'] = $this->parseOptions($uniqueXml->options->children());
|
||||
}
|
||||
|
||||
if (isset($uniqueXml['name'])) {
|
||||
$metadata->table['uniqueConstraints'][(string) $uniqueXml['name']] = $unique;
|
||||
} else {
|
||||
$metadata->table['uniqueConstraints'][] = $unique;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($xmlRoot->options)) {
|
||||
$metadata->table['options'] = $this->parseOptions($xmlRoot->options->children());
|
||||
}
|
||||
|
||||
// The mapping assignment is done in 2 times as a bug might occurs on some php/xml lib versions
|
||||
// The internal SimpleXmlIterator get resetted, to this generate a duplicate field exception
|
||||
// Evaluate <field ...> mappings
|
||||
if (isset($xmlRoot->field)) {
|
||||
foreach ($xmlRoot->field as $fieldMapping) {
|
||||
$mapping = $this->columnToArray($fieldMapping);
|
||||
|
||||
if (isset($mapping['version'])) {
|
||||
$metadata->setVersionMapping($mapping);
|
||||
unset($mapping['version']);
|
||||
}
|
||||
|
||||
$metadata->mapField($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($xmlRoot->embedded)) {
|
||||
foreach ($xmlRoot->embedded as $embeddedMapping) {
|
||||
$columnPrefix = isset($embeddedMapping['column-prefix'])
|
||||
? (string) $embeddedMapping['column-prefix']
|
||||
: null;
|
||||
|
||||
$useColumnPrefix = isset($embeddedMapping['use-column-prefix'])
|
||||
? $this->evaluateBoolean($embeddedMapping['use-column-prefix'])
|
||||
: true;
|
||||
|
||||
$mapping = [
|
||||
'fieldName' => (string) $embeddedMapping['name'],
|
||||
'class' => isset($embeddedMapping['class']) ? (string) $embeddedMapping['class'] : null,
|
||||
'columnPrefix' => $useColumnPrefix ? $columnPrefix : false,
|
||||
];
|
||||
|
||||
$metadata->mapEmbedded($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate <id ...> mappings
|
||||
$associationIds = [];
|
||||
foreach ($xmlRoot->id ?? [] as $idElement) {
|
||||
if (isset($idElement['association-key']) && $this->evaluateBoolean($idElement['association-key'])) {
|
||||
$associationIds[(string) $idElement['name']] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$mapping = $this->columnToArray($idElement);
|
||||
$mapping['id'] = true;
|
||||
|
||||
$metadata->mapField($mapping);
|
||||
|
||||
if (isset($idElement->generator)) {
|
||||
$strategy = isset($idElement->generator['strategy']) ?
|
||||
(string) $idElement->generator['strategy'] : 'AUTO';
|
||||
$metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
|
||||
. $strategy));
|
||||
}
|
||||
|
||||
// Check for SequenceGenerator/TableGenerator definition
|
||||
if (isset($idElement->{'sequence-generator'})) {
|
||||
$seqGenerator = $idElement->{'sequence-generator'};
|
||||
$metadata->setSequenceGeneratorDefinition(
|
||||
[
|
||||
'sequenceName' => (string) $seqGenerator['sequence-name'],
|
||||
'allocationSize' => (string) $seqGenerator['allocation-size'],
|
||||
'initialValue' => (string) $seqGenerator['initial-value'],
|
||||
],
|
||||
);
|
||||
} elseif (isset($idElement->{'custom-id-generator'})) {
|
||||
$customGenerator = $idElement->{'custom-id-generator'};
|
||||
$metadata->setCustomGeneratorDefinition(
|
||||
[
|
||||
'class' => (string) $customGenerator['class'],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate <one-to-one ...> mappings
|
||||
if (isset($xmlRoot->{'one-to-one'})) {
|
||||
foreach ($xmlRoot->{'one-to-one'} as $oneToOneElement) {
|
||||
$mapping = [
|
||||
'fieldName' => (string) $oneToOneElement['field'],
|
||||
];
|
||||
|
||||
if (isset($oneToOneElement['target-entity'])) {
|
||||
$mapping['targetEntity'] = (string) $oneToOneElement['target-entity'];
|
||||
}
|
||||
|
||||
if (isset($associationIds[$mapping['fieldName']])) {
|
||||
$mapping['id'] = true;
|
||||
}
|
||||
|
||||
if (isset($oneToOneElement['fetch'])) {
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $oneToOneElement['fetch']);
|
||||
}
|
||||
|
||||
if (isset($oneToOneElement['mapped-by'])) {
|
||||
$mapping['mappedBy'] = (string) $oneToOneElement['mapped-by'];
|
||||
} else {
|
||||
if (isset($oneToOneElement['inversed-by'])) {
|
||||
$mapping['inversedBy'] = (string) $oneToOneElement['inversed-by'];
|
||||
}
|
||||
|
||||
$joinColumns = [];
|
||||
|
||||
if (isset($oneToOneElement->{'join-column'})) {
|
||||
$joinColumns[] = $this->joinColumnToArray($oneToOneElement->{'join-column'});
|
||||
} elseif (isset($oneToOneElement->{'join-columns'})) {
|
||||
foreach ($oneToOneElement->{'join-columns'}->{'join-column'} ?? [] as $joinColumnElement) {
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
$mapping['joinColumns'] = $joinColumns;
|
||||
}
|
||||
|
||||
if (isset($oneToOneElement->cascade)) {
|
||||
$mapping['cascade'] = $this->getCascadeMappings($oneToOneElement->cascade);
|
||||
}
|
||||
|
||||
if (isset($oneToOneElement['orphan-removal'])) {
|
||||
$mapping['orphanRemoval'] = $this->evaluateBoolean($oneToOneElement['orphan-removal']);
|
||||
}
|
||||
|
||||
// Evaluate second level cache
|
||||
if (isset($oneToOneElement->cache)) {
|
||||
$mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToOneElement->cache));
|
||||
}
|
||||
|
||||
$metadata->mapOneToOne($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate <one-to-many ...> mappings
|
||||
if (isset($xmlRoot->{'one-to-many'})) {
|
||||
foreach ($xmlRoot->{'one-to-many'} as $oneToManyElement) {
|
||||
$mapping = [
|
||||
'fieldName' => (string) $oneToManyElement['field'],
|
||||
'mappedBy' => (string) $oneToManyElement['mapped-by'],
|
||||
];
|
||||
|
||||
if (isset($oneToManyElement['target-entity'])) {
|
||||
$mapping['targetEntity'] = (string) $oneToManyElement['target-entity'];
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement['fetch'])) {
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $oneToManyElement['fetch']);
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement->cascade)) {
|
||||
$mapping['cascade'] = $this->getCascadeMappings($oneToManyElement->cascade);
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement['orphan-removal'])) {
|
||||
$mapping['orphanRemoval'] = $this->evaluateBoolean($oneToManyElement['orphan-removal']);
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement->{'order-by'})) {
|
||||
$orderBy = [];
|
||||
foreach ($oneToManyElement->{'order-by'}->{'order-by-field'} ?? [] as $orderByField) {
|
||||
$orderBy[(string) $orderByField['name']] = (string) ($orderByField['direction'] ?? 'ASC');
|
||||
}
|
||||
|
||||
$mapping['orderBy'] = $orderBy;
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement['index-by'])) {
|
||||
$mapping['indexBy'] = (string) $oneToManyElement['index-by'];
|
||||
} elseif (isset($oneToManyElement->{'index-by'})) {
|
||||
throw new InvalidArgumentException('<index-by /> is not a valid tag');
|
||||
}
|
||||
|
||||
// Evaluate second level cache
|
||||
if (isset($oneToManyElement->cache)) {
|
||||
$mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToManyElement->cache));
|
||||
}
|
||||
|
||||
$metadata->mapOneToMany($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate <many-to-one ...> mappings
|
||||
if (isset($xmlRoot->{'many-to-one'})) {
|
||||
foreach ($xmlRoot->{'many-to-one'} as $manyToOneElement) {
|
||||
$mapping = [
|
||||
'fieldName' => (string) $manyToOneElement['field'],
|
||||
];
|
||||
|
||||
if (isset($manyToOneElement['target-entity'])) {
|
||||
$mapping['targetEntity'] = (string) $manyToOneElement['target-entity'];
|
||||
}
|
||||
|
||||
if (isset($associationIds[$mapping['fieldName']])) {
|
||||
$mapping['id'] = true;
|
||||
}
|
||||
|
||||
if (isset($manyToOneElement['fetch'])) {
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $manyToOneElement['fetch']);
|
||||
}
|
||||
|
||||
if (isset($manyToOneElement['inversed-by'])) {
|
||||
$mapping['inversedBy'] = (string) $manyToOneElement['inversed-by'];
|
||||
}
|
||||
|
||||
$joinColumns = [];
|
||||
|
||||
if (isset($manyToOneElement->{'join-column'})) {
|
||||
$joinColumns[] = $this->joinColumnToArray($manyToOneElement->{'join-column'});
|
||||
} elseif (isset($manyToOneElement->{'join-columns'})) {
|
||||
foreach ($manyToOneElement->{'join-columns'}->{'join-column'} ?? [] as $joinColumnElement) {
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
$mapping['joinColumns'] = $joinColumns;
|
||||
|
||||
if (isset($manyToOneElement->cascade)) {
|
||||
$mapping['cascade'] = $this->getCascadeMappings($manyToOneElement->cascade);
|
||||
}
|
||||
|
||||
// Evaluate second level cache
|
||||
if (isset($manyToOneElement->cache)) {
|
||||
$mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToOneElement->cache));
|
||||
}
|
||||
|
||||
$metadata->mapManyToOne($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate <many-to-many ...> mappings
|
||||
if (isset($xmlRoot->{'many-to-many'})) {
|
||||
foreach ($xmlRoot->{'many-to-many'} as $manyToManyElement) {
|
||||
$mapping = [
|
||||
'fieldName' => (string) $manyToManyElement['field'],
|
||||
];
|
||||
|
||||
if (isset($manyToManyElement['target-entity'])) {
|
||||
$mapping['targetEntity'] = (string) $manyToManyElement['target-entity'];
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['fetch'])) {
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $manyToManyElement['fetch']);
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['orphan-removal'])) {
|
||||
$mapping['orphanRemoval'] = $this->evaluateBoolean($manyToManyElement['orphan-removal']);
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['mapped-by'])) {
|
||||
$mapping['mappedBy'] = (string) $manyToManyElement['mapped-by'];
|
||||
} elseif (isset($manyToManyElement->{'join-table'})) {
|
||||
if (isset($manyToManyElement['inversed-by'])) {
|
||||
$mapping['inversedBy'] = (string) $manyToManyElement['inversed-by'];
|
||||
}
|
||||
|
||||
$joinTableElement = $manyToManyElement->{'join-table'};
|
||||
$joinTable = [
|
||||
'name' => (string) $joinTableElement['name'],
|
||||
];
|
||||
|
||||
if (isset($joinTableElement['schema'])) {
|
||||
$joinTable['schema'] = (string) $joinTableElement['schema'];
|
||||
}
|
||||
|
||||
if (isset($joinTableElement->options)) {
|
||||
$joinTable['options'] = $this->parseOptions($joinTableElement->options->children());
|
||||
}
|
||||
|
||||
foreach ($joinTableElement->{'join-columns'}->{'join-column'} ?? [] as $joinColumnElement) {
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
|
||||
foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} ?? [] as $joinColumnElement) {
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
|
||||
$mapping['joinTable'] = $joinTable;
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement->cascade)) {
|
||||
$mapping['cascade'] = $this->getCascadeMappings($manyToManyElement->cascade);
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement->{'order-by'})) {
|
||||
$orderBy = [];
|
||||
foreach ($manyToManyElement->{'order-by'}->{'order-by-field'} ?? [] as $orderByField) {
|
||||
$orderBy[(string) $orderByField['name']] = (string) ($orderByField['direction'] ?? 'ASC');
|
||||
}
|
||||
|
||||
$mapping['orderBy'] = $orderBy;
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['index-by'])) {
|
||||
$mapping['indexBy'] = (string) $manyToManyElement['index-by'];
|
||||
} elseif (isset($manyToManyElement->{'index-by'})) {
|
||||
throw new InvalidArgumentException('<index-by /> is not a valid tag');
|
||||
}
|
||||
|
||||
// Evaluate second level cache
|
||||
if (isset($manyToManyElement->cache)) {
|
||||
$mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToManyElement->cache));
|
||||
}
|
||||
|
||||
$metadata->mapManyToMany($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate association-overrides
|
||||
if (isset($xmlRoot->{'attribute-overrides'})) {
|
||||
foreach ($xmlRoot->{'attribute-overrides'}->{'attribute-override'} ?? [] as $overrideElement) {
|
||||
$fieldName = (string) $overrideElement['name'];
|
||||
foreach ($overrideElement->field ?? [] as $field) {
|
||||
$mapping = $this->columnToArray($field);
|
||||
$mapping['fieldName'] = $fieldName;
|
||||
$metadata->setAttributeOverride($fieldName, $mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate association-overrides
|
||||
if (isset($xmlRoot->{'association-overrides'})) {
|
||||
foreach ($xmlRoot->{'association-overrides'}->{'association-override'} ?? [] as $overrideElement) {
|
||||
$fieldName = (string) $overrideElement['name'];
|
||||
$override = [];
|
||||
|
||||
// Check for join-columns
|
||||
if (isset($overrideElement->{'join-columns'})) {
|
||||
$joinColumns = [];
|
||||
foreach ($overrideElement->{'join-columns'}->{'join-column'} ?? [] as $joinColumnElement) {
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
|
||||
$override['joinColumns'] = $joinColumns;
|
||||
}
|
||||
|
||||
// Check for join-table
|
||||
if ($overrideElement->{'join-table'}) {
|
||||
$joinTable = null;
|
||||
$joinTableElement = $overrideElement->{'join-table'};
|
||||
|
||||
$joinTable = [
|
||||
'name' => (string) $joinTableElement['name'],
|
||||
'schema' => (string) $joinTableElement['schema'],
|
||||
];
|
||||
|
||||
if (isset($joinTableElement->options)) {
|
||||
$joinTable['options'] = $this->parseOptions($joinTableElement->options->children());
|
||||
}
|
||||
|
||||
if (isset($joinTableElement->{'join-columns'})) {
|
||||
foreach ($joinTableElement->{'join-columns'}->{'join-column'} ?? [] as $joinColumnElement) {
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($joinTableElement->{'inverse-join-columns'})) {
|
||||
foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} ?? [] as $joinColumnElement) {
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
$override['joinTable'] = $joinTable;
|
||||
}
|
||||
|
||||
// Check for inversed-by
|
||||
if (isset($overrideElement->{'inversed-by'})) {
|
||||
$override['inversedBy'] = (string) $overrideElement->{'inversed-by'}['name'];
|
||||
}
|
||||
|
||||
// Check for `fetch`
|
||||
if (isset($overrideElement['fetch'])) {
|
||||
$override['fetch'] = constant(ClassMetadata::class . '::FETCH_' . (string) $overrideElement['fetch']);
|
||||
}
|
||||
|
||||
$metadata->setAssociationOverride($fieldName, $override);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate <lifecycle-callbacks...>
|
||||
if (isset($xmlRoot->{'lifecycle-callbacks'})) {
|
||||
foreach ($xmlRoot->{'lifecycle-callbacks'}->{'lifecycle-callback'} ?? [] as $lifecycleCallback) {
|
||||
$metadata->addLifecycleCallback((string) $lifecycleCallback['method'], constant('Doctrine\ORM\Events::' . (string) $lifecycleCallback['type']));
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate entity listener
|
||||
if (isset($xmlRoot->{'entity-listeners'})) {
|
||||
foreach ($xmlRoot->{'entity-listeners'}->{'entity-listener'} ?? [] as $listenerElement) {
|
||||
$className = (string) $listenerElement['class'];
|
||||
// Evaluate the listener using naming convention.
|
||||
if ($listenerElement->count() === 0) {
|
||||
EntityListenerBuilder::bindEntityListener($metadata, $className);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($listenerElement as $callbackElement) {
|
||||
$eventName = (string) $callbackElement['type'];
|
||||
$methodName = (string) $callbackElement['method'];
|
||||
|
||||
$metadata->addEntityListener($eventName, $className, $methodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses (nested) option elements.
|
||||
*
|
||||
* @return mixed[] The options array.
|
||||
* @phpstan-return array<int|string, array<int|string, mixed|string>|bool|string|object>
|
||||
*/
|
||||
private function parseOptions(SimpleXMLElement|null $options): array
|
||||
{
|
||||
$array = [];
|
||||
|
||||
foreach ($options ?? [] as $option) {
|
||||
$value = null;
|
||||
if ($option->count()) {
|
||||
// Check if this option contains an <object> element
|
||||
$children = $option->children();
|
||||
$hasObjectElement = false;
|
||||
|
||||
foreach ($children as $child) {
|
||||
if ($child->getName() === 'object') {
|
||||
$value = $this->parseObjectElement($child);
|
||||
$hasObjectElement = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $hasObjectElement) {
|
||||
$value = $this->parseOptions($children);
|
||||
}
|
||||
} else {
|
||||
$value = (string) $option;
|
||||
}
|
||||
|
||||
$attributes = $option->attributes();
|
||||
|
||||
if (isset($attributes->name)) {
|
||||
$nameAttribute = (string) $attributes->name;
|
||||
$array[$nameAttribute] = in_array($nameAttribute, ['unsigned', 'fixed'], true)
|
||||
? $this->evaluateBoolean($value)
|
||||
: $value;
|
||||
} else {
|
||||
$array[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an <object> element and returns the instantiated object.
|
||||
*
|
||||
* @param SimpleXMLElement $objectElement The XML element.
|
||||
*
|
||||
* @return object The instantiated object.
|
||||
*
|
||||
* @throws MappingException If the object specification is invalid.
|
||||
* @throws InvalidArgumentException If the class does not exist.
|
||||
*/
|
||||
private function parseObjectElement(SimpleXMLElement $objectElement): object
|
||||
{
|
||||
$attributes = $objectElement->attributes();
|
||||
|
||||
if (! isset($attributes->class)) {
|
||||
throw MappingException::missingRequiredOption('object', 'class');
|
||||
}
|
||||
|
||||
$className = (string) $attributes->class;
|
||||
|
||||
if (! class_exists($className)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" does not exist', $className));
|
||||
}
|
||||
|
||||
return new $className();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a joinColumn mapping array based on the information
|
||||
* found in the given SimpleXMLElement.
|
||||
*
|
||||
* @param SimpleXMLElement $joinColumnElement The XML element.
|
||||
*
|
||||
* @return mixed[] The mapping array.
|
||||
* @phpstan-return array{
|
||||
* name: string,
|
||||
* referencedColumnName: string,
|
||||
* unique?: bool,
|
||||
* nullable?: bool,
|
||||
* onDelete?: string,
|
||||
* columnDefinition?: string,
|
||||
* options?: mixed[]
|
||||
* }
|
||||
*/
|
||||
private function joinColumnToArray(SimpleXMLElement $joinColumnElement): array
|
||||
{
|
||||
$joinColumn = [
|
||||
'name' => (string) $joinColumnElement['name'],
|
||||
'referencedColumnName' => (string) $joinColumnElement['referenced-column-name'],
|
||||
];
|
||||
|
||||
if (isset($joinColumnElement['unique'])) {
|
||||
$joinColumn['unique'] = $this->evaluateBoolean($joinColumnElement['unique']);
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['nullable'])) {
|
||||
$joinColumn['nullable'] = $this->evaluateBoolean($joinColumnElement['nullable']);
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['on-delete'])) {
|
||||
$joinColumn['onDelete'] = (string) $joinColumnElement['on-delete'];
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['column-definition'])) {
|
||||
$joinColumn['columnDefinition'] = (string) $joinColumnElement['column-definition'];
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['options'])) {
|
||||
$joinColumn['options'] = $this->parseOptions($joinColumnElement['options'] ? $joinColumnElement['options']->children() : null);
|
||||
}
|
||||
|
||||
return $joinColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given field as array.
|
||||
*
|
||||
* @return mixed[]
|
||||
* @phpstan-return array{
|
||||
* fieldName: string,
|
||||
* type?: string,
|
||||
* columnName?: string,
|
||||
* length?: int,
|
||||
* precision?: int,
|
||||
* scale?: int,
|
||||
* unique?: bool,
|
||||
* nullable?: bool,
|
||||
* index?: bool,
|
||||
* notInsertable?: bool,
|
||||
* notUpdatable?: bool,
|
||||
* enumType?: string,
|
||||
* version?: bool,
|
||||
* columnDefinition?: string,
|
||||
* options?: array
|
||||
* }
|
||||
*/
|
||||
private function columnToArray(SimpleXMLElement $fieldMapping): array
|
||||
{
|
||||
$mapping = [
|
||||
'fieldName' => (string) $fieldMapping['name'],
|
||||
];
|
||||
|
||||
if (isset($fieldMapping['type'])) {
|
||||
$mapping['type'] = (string) $fieldMapping['type'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['column'])) {
|
||||
$mapping['columnName'] = (string) $fieldMapping['column'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['length'])) {
|
||||
$mapping['length'] = (int) $fieldMapping['length'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['precision'])) {
|
||||
$mapping['precision'] = (int) $fieldMapping['precision'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['scale'])) {
|
||||
$mapping['scale'] = (int) $fieldMapping['scale'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['unique'])) {
|
||||
$mapping['unique'] = $this->evaluateBoolean($fieldMapping['unique']);
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['index'])) {
|
||||
$mapping['index'] = $this->evaluateBoolean($fieldMapping['index']);
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['nullable'])) {
|
||||
$mapping['nullable'] = $this->evaluateBoolean($fieldMapping['nullable']);
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['insertable']) && ! $this->evaluateBoolean($fieldMapping['insertable'])) {
|
||||
$mapping['notInsertable'] = true;
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['updatable']) && ! $this->evaluateBoolean($fieldMapping['updatable'])) {
|
||||
$mapping['notUpdatable'] = true;
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['generated'])) {
|
||||
$mapping['generated'] = constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATED_' . (string) $fieldMapping['generated']);
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
|
||||
$mapping['version'] = $this->evaluateBoolean($fieldMapping['version']);
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['column-definition'])) {
|
||||
$mapping['columnDefinition'] = (string) $fieldMapping['column-definition'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['enum-type'])) {
|
||||
$mapping['enumType'] = (string) $fieldMapping['enum-type'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping->options)) {
|
||||
$mapping['options'] = $this->parseOptions($fieldMapping->options->children());
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse / Normalize the cache configuration
|
||||
*
|
||||
* @return mixed[]
|
||||
* @phpstan-return array{usage: int|null, region?: string}
|
||||
*/
|
||||
private function cacheToArray(SimpleXMLElement $cacheMapping): array
|
||||
{
|
||||
$region = isset($cacheMapping['region']) ? (string) $cacheMapping['region'] : null;
|
||||
$usage = isset($cacheMapping['usage']) ? strtoupper((string) $cacheMapping['usage']) : null;
|
||||
|
||||
if ($usage && ! defined('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid cache usage "%s"', $usage));
|
||||
}
|
||||
|
||||
if ($usage) {
|
||||
$usage = (int) constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage);
|
||||
}
|
||||
|
||||
return [
|
||||
'usage' => $usage,
|
||||
'region' => $region,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gathers a list of cascade options found in the given cascade element.
|
||||
*
|
||||
* @param SimpleXMLElement $cascadeElement The cascade element.
|
||||
*
|
||||
* @return string[] The list of cascade options.
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
private function getCascadeMappings(SimpleXMLElement $cascadeElement): array
|
||||
{
|
||||
$cascades = [];
|
||||
$children = $cascadeElement->children();
|
||||
assert($children !== null);
|
||||
|
||||
foreach ($children as $action) {
|
||||
// According to the JPA specifications, XML uses "cascade-persist"
|
||||
// instead of "persist". Here, both variations
|
||||
// are supported because Attribute uses "persist"
|
||||
// and we want to make sure that this driver doesn't need to know
|
||||
// anything about the supported cascading actions
|
||||
$cascades[] = str_replace('cascade-', '', $action->getName());
|
||||
}
|
||||
|
||||
return $cascades;
|
||||
}
|
||||
|
||||
/** @return array<class-string, SimpleXMLElement> */
|
||||
private function doLoadMappingFile(string $file): array
|
||||
{
|
||||
$this->validateMapping($file);
|
||||
$result = [];
|
||||
// Note: we do not use `simplexml_load_file()` because of https://bugs.php.net/bug.php?id=62577
|
||||
$xmlElement = simplexml_load_string(file_get_contents($file));
|
||||
assert($xmlElement !== false);
|
||||
|
||||
if (isset($xmlElement->entity)) {
|
||||
foreach ($xmlElement->entity as $entityElement) {
|
||||
/** @var class-string $entityName */
|
||||
$entityName = (string) $entityElement['name'];
|
||||
$result[$entityName] = $entityElement;
|
||||
}
|
||||
} elseif (isset($xmlElement->{'mapped-superclass'})) {
|
||||
foreach ($xmlElement->{'mapped-superclass'} as $mappedSuperClass) {
|
||||
/** @var class-string $className */
|
||||
$className = (string) $mappedSuperClass['name'];
|
||||
$result[$className] = $mappedSuperClass;
|
||||
}
|
||||
} elseif (isset($xmlElement->embeddable)) {
|
||||
foreach ($xmlElement->embeddable as $embeddableElement) {
|
||||
/** @var class-string $embeddableName */
|
||||
$embeddableName = (string) $embeddableElement['name'];
|
||||
$result[$embeddableName] = $embeddableElement;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function validateMapping(string $file): void
|
||||
{
|
||||
if (! $this->isXsdValidationEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$backedUpErrorSetting = libxml_use_internal_errors(true);
|
||||
|
||||
try {
|
||||
$document = new DOMDocument();
|
||||
$document->load($file);
|
||||
|
||||
if (! $document->schemaValidate(__DIR__ . '/../../../doctrine-mapping.xsd')) {
|
||||
throw MappingException::fromLibXmlErrors(libxml_get_errors());
|
||||
}
|
||||
} finally {
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors($backedUpErrorSetting);
|
||||
}
|
||||
}
|
||||
|
||||
protected function evaluateBoolean(mixed $element): bool
|
||||
{
|
||||
$flag = (string) $element;
|
||||
|
||||
return $flag === 'true' || $flag === '1';
|
||||
}
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/Embeddable.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/Embeddable.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class Embeddable implements MappingAttribute
|
||||
{
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Mapping/Embedded.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Mapping/Embedded.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class Embedded implements MappingAttribute
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string|null $class = null,
|
||||
public readonly string|bool|null $columnPrefix = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
93
backend/vendor/doctrine/orm/src/Mapping/EmbeddedClassMapping.php
vendored
Normal file
93
backend/vendor/doctrine/orm/src/Mapping/EmbeddedClassMapping.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
use function property_exists;
|
||||
|
||||
/** @template-implements ArrayAccess<string, mixed> */
|
||||
final class EmbeddedClassMapping implements ArrayAccess
|
||||
{
|
||||
use ArrayAccessImplementation;
|
||||
|
||||
public string|false|null $columnPrefix = null;
|
||||
public string|null $declaredField = null;
|
||||
public string|null $originalField = null;
|
||||
|
||||
/**
|
||||
* This is set when this embedded-class field is inherited by this class
|
||||
* from another (inheritance) parent <em>entity</em> class. The value is
|
||||
* the FQCN of the topmost entity class that contains mapping information
|
||||
* for this field. (If there are transient classes in the class hierarchy,
|
||||
* these are ignored, so the class property may in fact come from a class
|
||||
* further up in the PHP class hierarchy.) Fields initially declared in
|
||||
* mapped superclasses are <em>not</em> considered 'inherited' in the
|
||||
* nearest entity subclasses.
|
||||
*
|
||||
* @var class-string|null
|
||||
*/
|
||||
public string|null $inherited = null;
|
||||
|
||||
/**
|
||||
* This is set when the embedded-class field does not appear for the first
|
||||
* time in this class, but is originally declared in another parent
|
||||
* <em>entity or mapped superclass</em>. The value is the FQCN of the
|
||||
* topmost non-transient class that contains mapping information for this
|
||||
* field.
|
||||
*
|
||||
* @var class-string|null
|
||||
*/
|
||||
public string|null $declared = null;
|
||||
|
||||
/** @param class-string $class */
|
||||
public function __construct(public string $class)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param array{
|
||||
* class: class-string,
|
||||
* columnPrefix?: false|string|null,
|
||||
* declaredField?: string|null,
|
||||
* originalField?: string|null,
|
||||
* inherited?: class-string|null,
|
||||
* declared?: class-string|null,
|
||||
* } $mappingArray
|
||||
*/
|
||||
public static function fromMappingArray(array $mappingArray): self
|
||||
{
|
||||
$mapping = new self($mappingArray['class']);
|
||||
foreach ($mappingArray as $key => $value) {
|
||||
if ($key === 'class') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property_exists($mapping, $key)) {
|
||||
$mapping->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function __sleep(): array
|
||||
{
|
||||
$serialized = ['class'];
|
||||
|
||||
if ($this->columnPrefix) {
|
||||
$serialized[] = 'columnPrefix';
|
||||
}
|
||||
|
||||
foreach (['declaredField', 'originalField', 'inherited', 'declared'] as $property) {
|
||||
if ($this->$property !== null) {
|
||||
$serialized[] = $property;
|
||||
}
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
20
backend/vendor/doctrine/orm/src/Mapping/Entity.php
vendored
Normal file
20
backend/vendor/doctrine/orm/src/Mapping/Entity.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
/** @template T of object */
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class Entity implements MappingAttribute
|
||||
{
|
||||
/** @phpstan-param class-string<EntityRepository<T>>|null $repositoryClass */
|
||||
public function __construct(
|
||||
public readonly string|null $repositoryClass = null,
|
||||
public readonly bool $readOnly = false,
|
||||
) {
|
||||
}
|
||||
}
|
||||
30
backend/vendor/doctrine/orm/src/Mapping/EntityListenerResolver.php
vendored
Normal file
30
backend/vendor/doctrine/orm/src/Mapping/EntityListenerResolver.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* A resolver is used to instantiate an entity listener.
|
||||
*/
|
||||
interface EntityListenerResolver
|
||||
{
|
||||
/**
|
||||
* Clear all instances from the set, or a specific instance when given its identifier.
|
||||
*
|
||||
* @param string|null $className May be any arbitrary string. Name kept for BC only.
|
||||
*/
|
||||
public function clear(string|null $className = null): void;
|
||||
|
||||
/**
|
||||
* Returns a entity listener instance for the given identifier.
|
||||
*
|
||||
* @param string $className May be any arbitrary string. Name kept for BC only.
|
||||
*/
|
||||
public function resolve(string $className): object;
|
||||
|
||||
/**
|
||||
* Register a entity listener instance.
|
||||
*/
|
||||
public function register(object $object): void;
|
||||
}
|
||||
21
backend/vendor/doctrine/orm/src/Mapping/EntityListeners.php
vendored
Normal file
21
backend/vendor/doctrine/orm/src/Mapping/EntityListeners.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
/**
|
||||
* The EntityListeners attribute specifies the callback listener classes to be used for an entity or mapped superclass.
|
||||
* The EntityListeners attribute may be applied to an entity class or mapped superclass.
|
||||
*/
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class EntityListeners implements MappingAttribute
|
||||
{
|
||||
/** @param array<string> $value */
|
||||
public function __construct(
|
||||
public readonly array $value = [],
|
||||
) {
|
||||
}
|
||||
}
|
||||
28
backend/vendor/doctrine/orm/src/Mapping/Exception/InvalidCustomGenerator.php
vendored
Normal file
28
backend/vendor/doctrine/orm/src/Mapping/Exception/InvalidCustomGenerator.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Exception;
|
||||
|
||||
use Doctrine\ORM\Exception\ORMException;
|
||||
use LogicException;
|
||||
|
||||
use function sprintf;
|
||||
use function var_export;
|
||||
|
||||
final class InvalidCustomGenerator extends LogicException implements ORMException
|
||||
{
|
||||
public static function onClassNotConfigured(): self
|
||||
{
|
||||
return new self('Cannot instantiate custom generator, no class has been defined');
|
||||
}
|
||||
|
||||
/** @param mixed[] $definition */
|
||||
public static function onMissingClass(array $definition): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Cannot instantiate custom generator : %s',
|
||||
var_export($definition, true),
|
||||
));
|
||||
}
|
||||
}
|
||||
16
backend/vendor/doctrine/orm/src/Mapping/Exception/UnknownGeneratorType.php
vendored
Normal file
16
backend/vendor/doctrine/orm/src/Mapping/Exception/UnknownGeneratorType.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Exception;
|
||||
|
||||
use Doctrine\ORM\Exception\ORMException;
|
||||
use LogicException;
|
||||
|
||||
final class UnknownGeneratorType extends LogicException implements ORMException
|
||||
{
|
||||
public static function create(int $generatorType): self
|
||||
{
|
||||
return new self('Unknown generator type: ' . $generatorType);
|
||||
}
|
||||
}
|
||||
175
backend/vendor/doctrine/orm/src/Mapping/FieldMapping.php
vendored
Normal file
175
backend/vendor/doctrine/orm/src/Mapping/FieldMapping.php
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use ArrayAccess;
|
||||
use BackedEnum;
|
||||
|
||||
use function in_array;
|
||||
use function property_exists;
|
||||
|
||||
/** @template-implements ArrayAccess<string, mixed> */
|
||||
final class FieldMapping implements ArrayAccess
|
||||
{
|
||||
use ArrayAccessImplementation;
|
||||
|
||||
/** The database length of the column. Optional. Default value taken from the type. */
|
||||
public int|null $length = null;
|
||||
/**
|
||||
* Marks the field as the primary key of the entity. Multiple
|
||||
* fields of an entity can have the id attribute, forming a composite key.
|
||||
*/
|
||||
public bool|null $id = null;
|
||||
public bool|null $nullable = null;
|
||||
public bool|null $notInsertable = null;
|
||||
public bool|null $notUpdatable = null;
|
||||
public string|null $columnDefinition = null;
|
||||
/** @phpstan-var ClassMetadata::GENERATED_*|null */
|
||||
public int|null $generated = null;
|
||||
/** @var class-string<BackedEnum>|null */
|
||||
public string|null $enumType = null;
|
||||
/**
|
||||
* The precision of a decimal column.
|
||||
* Only valid if the column type is decimal
|
||||
*/
|
||||
public int|null $precision = null;
|
||||
/**
|
||||
* The scale of a decimal column.
|
||||
* Only valid if the column type is decimal
|
||||
*/
|
||||
public int|null $scale = null;
|
||||
/** Whether a unique constraint should be generated for the column. */
|
||||
public bool|null $unique = null;
|
||||
/** Whether an index should be generated for the column. */
|
||||
public bool|null $index = null;
|
||||
/**
|
||||
* @var class-string|null This is set when the field is inherited by this
|
||||
* class from another (inheritance) parent <em>entity</em> class. The value
|
||||
* is the FQCN of the topmost entity class that contains mapping information
|
||||
* for this field. (If there are transient classes in the class hierarchy,
|
||||
* these are ignored, so the class property may in fact come from a class
|
||||
* further up in the PHP class hierarchy.)
|
||||
* Fields initially declared in mapped superclasses are
|
||||
* <em>not</em> considered 'inherited' in the nearest entity subclasses.
|
||||
*/
|
||||
public string|null $inherited = null;
|
||||
|
||||
/** @var class-string|null */
|
||||
public string|null $originalClass = null;
|
||||
public string|null $originalField = null;
|
||||
public bool|null $quoted = null;
|
||||
/**
|
||||
* @var class-string|null This is set when the field does not appear for
|
||||
* the first time in this class, but is originally declared in another
|
||||
* parent <em>entity or mapped superclass</em>. The value is the FQCN of
|
||||
* the topmost non-transient class that contains mapping information for
|
||||
* this field.
|
||||
*/
|
||||
public string|null $declared = null;
|
||||
public string|null $declaredField = null;
|
||||
public array|null $options = null;
|
||||
public bool|null $version = null;
|
||||
|
||||
/** @deprecated Use options with 'default' key instead */
|
||||
public string|int|null $default = null;
|
||||
|
||||
/**
|
||||
* @param string $type The type name of the mapped field. Can be one of
|
||||
* Doctrine's mapping types or a custom mapping type.
|
||||
* @param string $fieldName The name of the field in the Entity.
|
||||
* @param string $columnName The column name. Optional. Defaults to the field name.
|
||||
*/
|
||||
public function __construct(
|
||||
public string $type,
|
||||
public string $fieldName,
|
||||
public string $columnName,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $mappingArray
|
||||
* @phpstan-param array{
|
||||
* type: string,
|
||||
* fieldName: string,
|
||||
* columnName: string,
|
||||
* length?: int|null,
|
||||
* id?: bool|null,
|
||||
* nullable?: bool|null,
|
||||
* index?: bool|null,
|
||||
* notInsertable?: bool|null,
|
||||
* notUpdatable?: bool|null,
|
||||
* columnDefinition?: string|null,
|
||||
* generated?: ClassMetadata::GENERATED_*|null,
|
||||
* enumType?: string|null,
|
||||
* precision?: int|null,
|
||||
* scale?: int|null,
|
||||
* unique?: bool|null,
|
||||
* inherited?: string|null,
|
||||
* originalClass?: class-string|null,
|
||||
* originalField?: string|null,
|
||||
* quoted?: bool|null,
|
||||
* declared?: string|null,
|
||||
* declaredField?: string|null,
|
||||
* options?: array<string, mixed>|null,
|
||||
* version?: bool|null,
|
||||
* default?: string|int|null,
|
||||
* } $mappingArray
|
||||
*/
|
||||
public static function fromMappingArray(array $mappingArray): self
|
||||
{
|
||||
$mapping = new self(
|
||||
$mappingArray['type'],
|
||||
$mappingArray['fieldName'],
|
||||
$mappingArray['columnName'],
|
||||
);
|
||||
foreach ($mappingArray as $key => $value) {
|
||||
if (in_array($key, ['type', 'fieldName', 'columnName'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property_exists($mapping, $key)) {
|
||||
$mapping->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function __sleep(): array
|
||||
{
|
||||
$serialized = ['type', 'fieldName', 'columnName'];
|
||||
|
||||
foreach (['nullable', 'notInsertable', 'notUpdatable', 'id', 'unique', 'version', 'quoted', 'index'] as $boolKey) {
|
||||
if ($this->$boolKey) {
|
||||
$serialized[] = $boolKey;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (
|
||||
[
|
||||
'length',
|
||||
'columnDefinition',
|
||||
'generated',
|
||||
'enumType',
|
||||
'precision',
|
||||
'scale',
|
||||
'inherited',
|
||||
'originalClass',
|
||||
'originalField',
|
||||
'declared',
|
||||
'declaredField',
|
||||
'options',
|
||||
'default',
|
||||
] as $key
|
||||
) {
|
||||
if ($this->$key !== null) {
|
||||
$serialized[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Mapping/GeneratedValue.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Mapping/GeneratedValue.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class GeneratedValue implements MappingAttribute
|
||||
{
|
||||
/** @phpstan-param 'AUTO'|'SEQUENCE'|'IDENTITY'|'NONE'|'CUSTOM' $strategy */
|
||||
public function __construct(
|
||||
public readonly string $strategy = 'AUTO',
|
||||
) {
|
||||
}
|
||||
}
|
||||
33
backend/vendor/doctrine/orm/src/Mapping/GetReflectionClassImplementation.php
vendored
Normal file
33
backend/vendor/doctrine/orm/src/Mapping/GetReflectionClassImplementation.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\Persistence\Mapping\StaticReflectionService;
|
||||
use ReflectionClass;
|
||||
|
||||
use function class_exists;
|
||||
|
||||
if (! class_exists(StaticReflectionService::class)) {
|
||||
trait GetReflectionClassImplementation
|
||||
{
|
||||
public function getReflectionClass(): ReflectionClass
|
||||
{
|
||||
return $this->reflClass;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
trait GetReflectionClassImplementation
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Can return null when using static reflection, in violation of the LSP
|
||||
*/
|
||||
public function getReflectionClass(): ReflectionClass|null
|
||||
{
|
||||
return $this->reflClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/HasLifecycleCallbacks.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/HasLifecycleCallbacks.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class HasLifecycleCallbacks implements MappingAttribute
|
||||
{
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/Id.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/Id.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class Id implements MappingAttribute
|
||||
{
|
||||
}
|
||||
26
backend/vendor/doctrine/orm/src/Mapping/Index.php
vendored
Normal file
26
backend/vendor/doctrine/orm/src/Mapping/Index.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)]
|
||||
final class Index implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* @param array<string>|null $columns
|
||||
* @param array<string>|null $fields
|
||||
* @param array<string>|null $flags
|
||||
* @param array<string,mixed>|null $options
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string|null $name = null,
|
||||
public readonly array|null $columns = null,
|
||||
public readonly array|null $fields = null,
|
||||
public readonly array|null $flags = null,
|
||||
public readonly array|null $options = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Mapping/InheritanceType.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Mapping/InheritanceType.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class InheritanceType implements MappingAttribute
|
||||
{
|
||||
/** @phpstan-param 'NONE'|'JOINED'|'SINGLE_TABLE' $value */
|
||||
public function __construct(
|
||||
public readonly string $value,
|
||||
) {
|
||||
}
|
||||
}
|
||||
13
backend/vendor/doctrine/orm/src/Mapping/InverseJoinColumn.php
vendored
Normal file
13
backend/vendor/doctrine/orm/src/Mapping/InverseJoinColumn.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
|
||||
final class InverseJoinColumn implements MappingAttribute
|
||||
{
|
||||
use JoinColumnProperties;
|
||||
}
|
||||
30
backend/vendor/doctrine/orm/src/Mapping/InverseSideMapping.php
vendored
Normal file
30
backend/vendor/doctrine/orm/src/Mapping/InverseSideMapping.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
abstract class InverseSideMapping extends AssociationMapping
|
||||
{
|
||||
/**
|
||||
* required for bidirectional associations
|
||||
* The name of the field that completes the bidirectional association on
|
||||
* the owning side. This key must be specified on the inverse side of a
|
||||
* bidirectional association.
|
||||
*/
|
||||
public string $mappedBy;
|
||||
|
||||
final public function backRefFieldName(): string
|
||||
{
|
||||
return $this->mappedBy;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function __sleep(): array
|
||||
{
|
||||
return [
|
||||
...parent::__sleep(),
|
||||
'mappedBy',
|
||||
];
|
||||
}
|
||||
}
|
||||
13
backend/vendor/doctrine/orm/src/Mapping/JoinColumn.php
vendored
Normal file
13
backend/vendor/doctrine/orm/src/Mapping/JoinColumn.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
|
||||
final class JoinColumn implements MappingAttribute
|
||||
{
|
||||
use JoinColumnProperties;
|
||||
}
|
||||
78
backend/vendor/doctrine/orm/src/Mapping/JoinColumnMapping.php
vendored
Normal file
78
backend/vendor/doctrine/orm/src/Mapping/JoinColumnMapping.php
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
use function property_exists;
|
||||
|
||||
/** @template-implements ArrayAccess<string, mixed> */
|
||||
final class JoinColumnMapping implements ArrayAccess
|
||||
{
|
||||
use ArrayAccessImplementation;
|
||||
|
||||
public bool|null $deferrable = null;
|
||||
public bool|null $unique = null;
|
||||
public bool|null $quoted = null;
|
||||
public string|null $fieldName = null;
|
||||
public string|null $onDelete = null;
|
||||
public string|null $columnDefinition = null;
|
||||
public bool|null $nullable = null;
|
||||
|
||||
/** @var array<string, mixed>|null */
|
||||
public array|null $options = null;
|
||||
|
||||
public function __construct(
|
||||
public string $name,
|
||||
public string $referencedColumnName,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $mappingArray
|
||||
* @phpstan-param array{
|
||||
* name: string,
|
||||
* referencedColumnName: string|null,
|
||||
* unique?: bool|null,
|
||||
* quoted?: bool|null,
|
||||
* fieldName?: string|null,
|
||||
* onDelete?: string|null,
|
||||
* columnDefinition?: string|null,
|
||||
* nullable?: bool|null,
|
||||
* options?: array<string, mixed>|null,
|
||||
* } $mappingArray
|
||||
*/
|
||||
public static function fromMappingArray(array $mappingArray): self
|
||||
{
|
||||
$mapping = new self($mappingArray['name'], $mappingArray['referencedColumnName']);
|
||||
foreach ($mappingArray as $key => $value) {
|
||||
if (property_exists($mapping, $key) && $value !== null) {
|
||||
$mapping->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function __sleep(): array
|
||||
{
|
||||
$serialized = [];
|
||||
|
||||
foreach (['name', 'fieldName', 'onDelete', 'columnDefinition', 'referencedColumnName', 'options'] as $stringOrArrayKey) {
|
||||
if ($this->$stringOrArrayKey !== null) {
|
||||
$serialized[] = $stringOrArrayKey;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['deferrable', 'unique', 'quoted', 'nullable'] as $boolKey) {
|
||||
if ($this->$boolKey !== null) {
|
||||
$serialized[] = $boolKey;
|
||||
}
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
22
backend/vendor/doctrine/orm/src/Mapping/JoinColumnProperties.php
vendored
Normal file
22
backend/vendor/doctrine/orm/src/Mapping/JoinColumnProperties.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
trait JoinColumnProperties
|
||||
{
|
||||
/** @param array<string, mixed> $options */
|
||||
public function __construct(
|
||||
public readonly string|null $name = null,
|
||||
public readonly string|null $referencedColumnName = null,
|
||||
public readonly bool $deferrable = false,
|
||||
public readonly bool $unique = false,
|
||||
public readonly bool|null $nullable = null,
|
||||
public readonly mixed $onDelete = null,
|
||||
public readonly string|null $columnDefinition = null,
|
||||
public readonly string|null $fieldName = null,
|
||||
public readonly array $options = [],
|
||||
) {
|
||||
}
|
||||
}
|
||||
14
backend/vendor/doctrine/orm/src/Mapping/JoinColumns.php
vendored
Normal file
14
backend/vendor/doctrine/orm/src/Mapping/JoinColumns.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
final class JoinColumns implements MappingAttribute
|
||||
{
|
||||
/** @param array<JoinColumn> $value */
|
||||
public function __construct(
|
||||
public readonly array $value,
|
||||
) {
|
||||
}
|
||||
}
|
||||
35
backend/vendor/doctrine/orm/src/Mapping/JoinTable.php
vendored
Normal file
35
backend/vendor/doctrine/orm/src/Mapping/JoinTable.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class JoinTable implements MappingAttribute
|
||||
{
|
||||
/** @var array<JoinColumn> */
|
||||
public readonly array $joinColumns;
|
||||
|
||||
/** @var array<JoinColumn> */
|
||||
public readonly array $inverseJoinColumns;
|
||||
|
||||
/**
|
||||
* @param array<JoinColumn>|JoinColumn $joinColumns
|
||||
* @param array<JoinColumn>|JoinColumn $inverseJoinColumns
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string|null $name = null,
|
||||
public readonly string|null $schema = null,
|
||||
array|JoinColumn $joinColumns = [],
|
||||
array|JoinColumn $inverseJoinColumns = [],
|
||||
public readonly array $options = [],
|
||||
) {
|
||||
$this->joinColumns = $joinColumns instanceof JoinColumn ? [$joinColumns] : $joinColumns;
|
||||
$this->inverseJoinColumns = $inverseJoinColumns instanceof JoinColumn
|
||||
? [$inverseJoinColumns]
|
||||
: $inverseJoinColumns;
|
||||
}
|
||||
}
|
||||
120
backend/vendor/doctrine/orm/src/Mapping/JoinTableMapping.php
vendored
Normal file
120
backend/vendor/doctrine/orm/src/Mapping/JoinTableMapping.php
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
use function array_map;
|
||||
use function in_array;
|
||||
|
||||
/** @template-implements ArrayAccess<string, mixed> */
|
||||
final class JoinTableMapping implements ArrayAccess
|
||||
{
|
||||
use ArrayAccessImplementation;
|
||||
|
||||
public bool|null $quoted = null;
|
||||
|
||||
/** @var list<JoinColumnMapping> */
|
||||
public array $joinColumns = [];
|
||||
|
||||
/** @var list<JoinColumnMapping> */
|
||||
public array $inverseJoinColumns = [];
|
||||
|
||||
/** @var array<string, mixed> */
|
||||
public array $options = [];
|
||||
|
||||
public string|null $schema = null;
|
||||
|
||||
public function __construct(public string $name)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $mappingArray
|
||||
* @phpstan-param array{
|
||||
* name: string,
|
||||
* quoted?: bool|null,
|
||||
* joinColumns?: mixed[],
|
||||
* inverseJoinColumns?: mixed[],
|
||||
* schema?: string|null,
|
||||
* options?: array<string, mixed>
|
||||
* } $mappingArray
|
||||
*/
|
||||
public static function fromMappingArray(array $mappingArray): self
|
||||
{
|
||||
$mapping = new self($mappingArray['name']);
|
||||
|
||||
foreach (['quoted', 'schema', 'options'] as $key) {
|
||||
if (isset($mappingArray[$key])) {
|
||||
$mapping->$key = $mappingArray[$key];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($mappingArray['joinColumns'])) {
|
||||
foreach ($mappingArray['joinColumns'] as $column) {
|
||||
$mapping->joinColumns[] = JoinColumnMapping::fromMappingArray($column);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($mappingArray['inverseJoinColumns'])) {
|
||||
foreach ($mappingArray['inverseJoinColumns'] as $column) {
|
||||
$mapping->inverseJoinColumns[] = JoinColumnMapping::fromMappingArray($column);
|
||||
}
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
if (in_array($offset, ['joinColumns', 'inverseJoinColumns'], true)) {
|
||||
$joinColumns = [];
|
||||
foreach ($value as $column) {
|
||||
$joinColumns[] = JoinColumnMapping::fromMappingArray($column);
|
||||
}
|
||||
|
||||
$value = $joinColumns;
|
||||
}
|
||||
|
||||
$this->$offset = $value;
|
||||
}
|
||||
|
||||
/** @return mixed[] */
|
||||
public function toArray(): array
|
||||
{
|
||||
$array = (array) $this;
|
||||
$toArray = static function (JoinColumnMapping $column) {
|
||||
$array = (array) $column;
|
||||
|
||||
unset($array['nullable']);
|
||||
|
||||
return $array;
|
||||
};
|
||||
$array['joinColumns'] = array_map($toArray, $array['joinColumns']);
|
||||
$array['inverseJoinColumns'] = array_map($toArray, $array['inverseJoinColumns']);
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function __sleep(): array
|
||||
{
|
||||
$serialized = [];
|
||||
|
||||
foreach (['joinColumns', 'inverseJoinColumns', 'name', 'schema', 'options'] as $stringOrArrayKey) {
|
||||
if ($this->$stringOrArrayKey !== null) {
|
||||
$serialized[] = $stringOrArrayKey;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['quoted'] as $boolKey) {
|
||||
if ($this->$boolKey) {
|
||||
$serialized[] = $boolKey;
|
||||
}
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
170
backend/vendor/doctrine/orm/src/Mapping/LegacyReflectionFields.php
vendored
Normal file
170
backend/vendor/doctrine/orm/src/Mapping/LegacyReflectionFields.php
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use ArrayAccess;
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use Doctrine\Persistence\Mapping\ReflectionService;
|
||||
use Doctrine\Persistence\Reflection\EnumReflectionProperty;
|
||||
use Generator;
|
||||
use IteratorAggregate;
|
||||
use OutOfBoundsException;
|
||||
use ReflectionProperty;
|
||||
use Traversable;
|
||||
|
||||
use function array_keys;
|
||||
use function assert;
|
||||
use function is_string;
|
||||
use function str_contains;
|
||||
use function str_replace;
|
||||
|
||||
/**
|
||||
* @template-implements ArrayAccess<string, ReflectionProperty|null>
|
||||
* @template-implements IteratorAggregate<string, ReflectionProperty|null>
|
||||
*/
|
||||
class LegacyReflectionFields implements ArrayAccess, IteratorAggregate
|
||||
{
|
||||
/** @var array<string, ReflectionProperty|null> */
|
||||
private array $reflFields = [];
|
||||
|
||||
public function __construct(private ClassMetadata $classMetadata, private ReflectionService $reflectionService)
|
||||
{
|
||||
}
|
||||
|
||||
/** @param string $offset */
|
||||
public function offsetExists($offset): bool // phpcs:ignore
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/11659',
|
||||
'Access to ClassMetadata::$reflFields is deprecated and will be removed in Doctrine ORM 4.0.',
|
||||
);
|
||||
|
||||
return isset($this->classMetadata->propertyAccessors[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @psalm-suppress LessSpecificImplementedReturnType
|
||||
*/
|
||||
public function offsetGet($field): mixed // phpcs:ignore
|
||||
{
|
||||
if (isset($this->reflFields[$field])) {
|
||||
return $this->reflFields[$field];
|
||||
}
|
||||
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/11659',
|
||||
'Access to ClassMetadata::$reflFields is deprecated and will be removed in Doctrine ORM 4.0.',
|
||||
);
|
||||
|
||||
if (isset($this->classMetadata->propertyAccessors[$field])) {
|
||||
$fieldName = str_contains($field, '.') ? $this->classMetadata->fieldMappings[$field]->originalField : $field;
|
||||
$className = $this->classMetadata->name;
|
||||
|
||||
assert(is_string($fieldName));
|
||||
|
||||
if (isset($this->classMetadata->fieldMappings[$field]) && $this->classMetadata->fieldMappings[$field]->originalClass !== null) {
|
||||
$className = $this->classMetadata->fieldMappings[$field]->originalClass;
|
||||
} elseif (isset($this->classMetadata->fieldMappings[$field]) && $this->classMetadata->fieldMappings[$field]->declared !== null) {
|
||||
$className = $this->classMetadata->fieldMappings[$field]->declared;
|
||||
} elseif (isset($this->classMetadata->associationMappings[$field]) && $this->classMetadata->associationMappings[$field]->declared !== null) {
|
||||
$className = $this->classMetadata->associationMappings[$field]->declared;
|
||||
} elseif (isset($this->classMetadata->embeddedClasses[$field]) && $this->classMetadata->embeddedClasses[$field]->declared !== null) {
|
||||
$className = $this->classMetadata->embeddedClasses[$field]->declared;
|
||||
}
|
||||
|
||||
/** @psalm-suppress ArgumentTypeCoercion */
|
||||
$this->reflFields[$field] = $this->getAccessibleProperty($className, $fieldName);
|
||||
|
||||
if (isset($this->classMetadata->fieldMappings[$field])) {
|
||||
if ($this->classMetadata->fieldMappings[$field]->enumType !== null) {
|
||||
$this->reflFields[$field] = new EnumReflectionProperty(
|
||||
$this->reflFields[$field],
|
||||
$this->classMetadata->fieldMappings[$field]->enumType,
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->classMetadata->fieldMappings[$field]->originalField !== null) {
|
||||
$parentField = str_replace('.' . $fieldName, '', $field);
|
||||
$originalClass = $this->classMetadata->fieldMappings[$field]->originalClass;
|
||||
|
||||
if (! str_contains($parentField, '.')) {
|
||||
$parentClass = $this->classMetadata->name;
|
||||
} else {
|
||||
$parentClass = $this->classMetadata->fieldMappings[$parentField]->originalClass;
|
||||
}
|
||||
|
||||
/** @psalm-var class-string $parentClass */
|
||||
/** @psalm-var class-string $originalClass */
|
||||
|
||||
$this->reflFields[$field] = new ReflectionEmbeddedProperty(
|
||||
$this->getAccessibleProperty($parentClass, $parentField),
|
||||
$this->reflFields[$field],
|
||||
$originalClass,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->reflFields[$field];
|
||||
}
|
||||
|
||||
throw new OutOfBoundsException('Unknown field: ' . $this->classMetadata->name . ' ::$' . $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset
|
||||
* @param ReflectionProperty $value
|
||||
*/
|
||||
public function offsetSet($offset, $value): void // phpcs:ignore
|
||||
{
|
||||
$this->reflFields[$offset] = $value;
|
||||
}
|
||||
|
||||
/** @param string $offset */
|
||||
public function offsetUnset($offset): void // phpcs:ignore
|
||||
{
|
||||
unset($this->reflFields[$offset]);
|
||||
}
|
||||
|
||||
/** @psalm-param class-string $class */
|
||||
private function getAccessibleProperty(string $class, string $field): ReflectionProperty
|
||||
{
|
||||
$reflectionProperty = $this->reflectionService->getAccessibleProperty($class, $field);
|
||||
|
||||
assert($reflectionProperty !== null);
|
||||
|
||||
if ($reflectionProperty->isReadOnly()) {
|
||||
$declaringClass = $reflectionProperty->class;
|
||||
if ($declaringClass !== $class) {
|
||||
$reflectionProperty = $this->reflectionService->getAccessibleProperty($declaringClass, $field);
|
||||
|
||||
assert($reflectionProperty !== null);
|
||||
}
|
||||
|
||||
$reflectionProperty = new ReflectionReadonlyProperty($reflectionProperty);
|
||||
}
|
||||
|
||||
return $reflectionProperty;
|
||||
}
|
||||
|
||||
/** @return Generator<string, ReflectionProperty> */
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/11659',
|
||||
'Access to ClassMetadata::$reflFields is deprecated and will be removed in Doctrine ORM 4.0.',
|
||||
);
|
||||
|
||||
$keys = array_keys($this->classMetadata->propertyAccessors);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
yield $key => $this->offsetGet($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
backend/vendor/doctrine/orm/src/Mapping/ManyToMany.php
vendored
Normal file
27
backend/vendor/doctrine/orm/src/Mapping/ManyToMany.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class ManyToMany implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* @param class-string $targetEntity
|
||||
* @param string[]|null $cascade
|
||||
* @phpstan-param 'LAZY'|'EAGER'|'EXTRA_LAZY' $fetch
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $targetEntity,
|
||||
public readonly string|null $mappedBy = null,
|
||||
public readonly string|null $inversedBy = null,
|
||||
public readonly array|null $cascade = null,
|
||||
public readonly string $fetch = 'LAZY',
|
||||
public readonly bool $orphanRemoval = false,
|
||||
public readonly string|null $indexBy = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
9
backend/vendor/doctrine/orm/src/Mapping/ManyToManyAssociationMapping.php
vendored
Normal file
9
backend/vendor/doctrine/orm/src/Mapping/ManyToManyAssociationMapping.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
interface ManyToManyAssociationMapping extends ToManyAssociationMapping
|
||||
{
|
||||
}
|
||||
9
backend/vendor/doctrine/orm/src/Mapping/ManyToManyInverseSideMapping.php
vendored
Normal file
9
backend/vendor/doctrine/orm/src/Mapping/ManyToManyInverseSideMapping.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
final class ManyToManyInverseSideMapping extends ToManyInverseSideMapping implements ManyToManyAssociationMapping
|
||||
{
|
||||
}
|
||||
227
backend/vendor/doctrine/orm/src/Mapping/ManyToManyOwningSideMapping.php
vendored
Normal file
227
backend/vendor/doctrine/orm/src/Mapping/ManyToManyOwningSideMapping.php
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
use function strtolower;
|
||||
use function trim;
|
||||
|
||||
final class ManyToManyOwningSideMapping extends ToManyOwningSideMapping implements ManyToManyAssociationMapping
|
||||
{
|
||||
/**
|
||||
* Specification of the join table and its join columns (foreign keys).
|
||||
* Only valid for many-to-many mappings. Note that one-to-many associations
|
||||
* can be mapped through a join table by simply mapping the association as
|
||||
* many-to-many with a unique constraint on the join table.
|
||||
*/
|
||||
public JoinTableMapping $joinTable;
|
||||
|
||||
/** @var list<mixed> */
|
||||
public array $joinTableColumns = [];
|
||||
|
||||
/** @var array<string, string> */
|
||||
public array $relationToSourceKeyColumns = [];
|
||||
/** @var array<string, string> */
|
||||
public array $relationToTargetKeyColumns = [];
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function toArray(): array
|
||||
{
|
||||
$array = parent::toArray();
|
||||
|
||||
$array['joinTable'] = $this->joinTable->toArray();
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $mappingArray
|
||||
* @phpstan-param array{
|
||||
* fieldName: string,
|
||||
* sourceEntity: class-string,
|
||||
* targetEntity: class-string,
|
||||
* cascade?: list<'persist'|'remove'|'detach'|'refresh'|'all'>,
|
||||
* fetch?: ClassMetadata::FETCH_*|null,
|
||||
* inherited?: class-string|null,
|
||||
* declared?: class-string|null,
|
||||
* cache?: array<mixed>|null,
|
||||
* id?: bool|null,
|
||||
* isOnDeleteCascade?: bool|null,
|
||||
* originalClass?: class-string|null,
|
||||
* originalField?: string|null,
|
||||
* orphanRemoval?: bool,
|
||||
* unique?: bool|null,
|
||||
* joinTable?: mixed[]|null,
|
||||
* type?: int,
|
||||
* isOwningSide: bool,
|
||||
* } $mappingArray
|
||||
*/
|
||||
public static function fromMappingArrayAndNamingStrategy(array $mappingArray, NamingStrategy $namingStrategy): self
|
||||
{
|
||||
if (isset($mappingArray['joinTable']['joinColumns'])) {
|
||||
foreach ($mappingArray['joinTable']['joinColumns'] as $key => $joinColumn) {
|
||||
if (empty($joinColumn['referencedColumnName'])) {
|
||||
$mappingArray['joinTable']['joinColumns'][$key]['referencedColumnName'] = $namingStrategy->referenceColumnName();
|
||||
}
|
||||
|
||||
if (empty($joinColumn['name'])) {
|
||||
$mappingArray['joinTable']['joinColumns'][$key]['name'] = $namingStrategy->joinKeyColumnName(
|
||||
$mappingArray['sourceEntity'],
|
||||
$joinColumn['referencedColumnName'] ?? $namingStrategy->referenceColumnName(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($mappingArray['joinTable']['inverseJoinColumns'])) {
|
||||
foreach ($mappingArray['joinTable']['inverseJoinColumns'] as $key => $joinColumn) {
|
||||
if (empty($joinColumn['referencedColumnName'])) {
|
||||
$mappingArray['joinTable']['inverseJoinColumns'][$key]['referencedColumnName'] = $namingStrategy->referenceColumnName();
|
||||
}
|
||||
|
||||
if (empty($joinColumn['name'])) {
|
||||
$mappingArray['joinTable']['inverseJoinColumns'][$key]['name'] = $namingStrategy->joinKeyColumnName(
|
||||
$mappingArray['targetEntity'],
|
||||
$joinColumn['referencedColumnName'] ?? $namingStrategy->referenceColumnName(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// owning side MUST have a join table
|
||||
if (! isset($mappingArray['joinTable']) || ! isset($mappingArray['joinTable']['name'])) {
|
||||
$mappingArray['joinTable']['name'] = $namingStrategy->joinTableName(
|
||||
$mappingArray['sourceEntity'],
|
||||
$mappingArray['targetEntity'],
|
||||
$mappingArray['fieldName'],
|
||||
);
|
||||
}
|
||||
|
||||
$mapping = parent::fromMappingArray($mappingArray);
|
||||
|
||||
$selfReferencingEntityWithoutJoinColumns = $mapping->sourceEntity === $mapping->targetEntity
|
||||
&& $mapping->joinTable->joinColumns === []
|
||||
&& $mapping->joinTable->inverseJoinColumns === [];
|
||||
|
||||
if ($mapping->joinTable->joinColumns === []) {
|
||||
$mapping->joinTable->joinColumns = [
|
||||
JoinColumnMapping::fromMappingArray([
|
||||
'name' => $namingStrategy->joinKeyColumnName($mapping->sourceEntity, $selfReferencingEntityWithoutJoinColumns ? 'source' : null),
|
||||
'referencedColumnName' => $namingStrategy->referenceColumnName(),
|
||||
'onDelete' => 'CASCADE',
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
if ($mapping->joinTable->inverseJoinColumns === []) {
|
||||
$mapping->joinTable->inverseJoinColumns = [
|
||||
JoinColumnMapping::fromMappingArray([
|
||||
'name' => $namingStrategy->joinKeyColumnName($mapping->targetEntity, $selfReferencingEntityWithoutJoinColumns ? 'target' : null),
|
||||
'referencedColumnName' => $namingStrategy->referenceColumnName(),
|
||||
'onDelete' => 'CASCADE',
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
$mapping->joinTableColumns = [];
|
||||
|
||||
foreach ($mapping->joinTable->joinColumns as $joinColumn) {
|
||||
if ($joinColumn->nullable !== null) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/12126',
|
||||
<<<'DEPRECATION'
|
||||
Specifying the "nullable" attribute for join columns in many-to-many associations (here, %s::$%s) is a no-op.
|
||||
The ORM will always set it to false.
|
||||
Doing so is deprecated and will be an error in 4.0.
|
||||
DEPRECATION,
|
||||
$mapping->sourceEntity,
|
||||
$mapping->fieldName,
|
||||
);
|
||||
}
|
||||
|
||||
$joinColumn->nullable = false;
|
||||
|
||||
if (empty($joinColumn->referencedColumnName)) {
|
||||
$joinColumn->referencedColumnName = $namingStrategy->referenceColumnName();
|
||||
}
|
||||
|
||||
if ($joinColumn->name[0] === '`') {
|
||||
$joinColumn->name = trim($joinColumn->name, '`');
|
||||
$joinColumn->quoted = true;
|
||||
}
|
||||
|
||||
if ($joinColumn->referencedColumnName[0] === '`') {
|
||||
$joinColumn->referencedColumnName = trim($joinColumn->referencedColumnName, '`');
|
||||
$joinColumn->quoted = true;
|
||||
}
|
||||
|
||||
if (isset($joinColumn->onDelete) && strtolower($joinColumn->onDelete) === 'cascade') {
|
||||
$mapping->isOnDeleteCascade = true;
|
||||
}
|
||||
|
||||
$mapping->relationToSourceKeyColumns[$joinColumn->name] = $joinColumn->referencedColumnName;
|
||||
$mapping->joinTableColumns[] = $joinColumn->name;
|
||||
}
|
||||
|
||||
foreach ($mapping->joinTable->inverseJoinColumns as $inverseJoinColumn) {
|
||||
if ($inverseJoinColumn->nullable !== null) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/12126',
|
||||
<<<'DEPRECATION'
|
||||
Specifying the "nullable" attribute for join columns in many-to-many associations (here, %s::$%s) is a no-op.
|
||||
The ORM will always set it to false.
|
||||
Doing so is deprecated and will be an error in 4.0.
|
||||
DEPRECATION,
|
||||
$mapping->targetEntity,
|
||||
$mapping->fieldName,
|
||||
);
|
||||
}
|
||||
|
||||
$inverseJoinColumn->nullable = false;
|
||||
|
||||
if (empty($inverseJoinColumn->referencedColumnName)) {
|
||||
$inverseJoinColumn->referencedColumnName = $namingStrategy->referenceColumnName();
|
||||
}
|
||||
|
||||
if ($inverseJoinColumn->name[0] === '`') {
|
||||
$inverseJoinColumn->name = trim($inverseJoinColumn->name, '`');
|
||||
$inverseJoinColumn->quoted = true;
|
||||
}
|
||||
|
||||
if ($inverseJoinColumn->referencedColumnName[0] === '`') {
|
||||
$inverseJoinColumn->referencedColumnName = trim($inverseJoinColumn->referencedColumnName, '`');
|
||||
$inverseJoinColumn->quoted = true;
|
||||
}
|
||||
|
||||
if (isset($inverseJoinColumn->onDelete) && strtolower($inverseJoinColumn->onDelete) === 'cascade') {
|
||||
$mapping->isOnDeleteCascade = true;
|
||||
}
|
||||
|
||||
$mapping->relationToTargetKeyColumns[$inverseJoinColumn->name] = $inverseJoinColumn->referencedColumnName;
|
||||
$mapping->joinTableColumns[] = $inverseJoinColumn->name;
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function __sleep(): array
|
||||
{
|
||||
$serialized = parent::__sleep();
|
||||
$serialized[] = 'joinTable';
|
||||
$serialized[] = 'joinTableColumns';
|
||||
|
||||
foreach (['relationToSourceKeyColumns', 'relationToTargetKeyColumns'] as $arrayKey) {
|
||||
if ($this->$arrayKey !== null) {
|
||||
$serialized[] = $arrayKey;
|
||||
}
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
24
backend/vendor/doctrine/orm/src/Mapping/ManyToOne.php
vendored
Normal file
24
backend/vendor/doctrine/orm/src/Mapping/ManyToOne.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class ManyToOne implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* @param class-string|null $targetEntity
|
||||
* @param string[]|null $cascade
|
||||
* @phpstan-param 'LAZY'|'EAGER'|'EXTRA_LAZY' $fetch
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string|null $targetEntity = null,
|
||||
public readonly array|null $cascade = null,
|
||||
public readonly string $fetch = 'LAZY',
|
||||
public readonly string|null $inversedBy = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/ManyToOneAssociationMapping.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/ManyToOneAssociationMapping.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* The "many" side of a many-to-one association mapping is always the owning side.
|
||||
*/
|
||||
final class ManyToOneAssociationMapping extends ToOneOwningSideMapping
|
||||
{
|
||||
}
|
||||
18
backend/vendor/doctrine/orm/src/Mapping/MappedSuperclass.php
vendored
Normal file
18
backend/vendor/doctrine/orm/src/Mapping/MappedSuperclass.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class MappedSuperclass implements MappingAttribute
|
||||
{
|
||||
/** @param class-string<EntityRepository>|null $repositoryClass */
|
||||
public function __construct(
|
||||
public readonly string|null $repositoryClass = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
10
backend/vendor/doctrine/orm/src/Mapping/MappingAttribute.php
vendored
Normal file
10
backend/vendor/doctrine/orm/src/Mapping/MappingAttribute.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/** A marker interface for mapping attributes. */
|
||||
interface MappingAttribute
|
||||
{
|
||||
}
|
||||
718
backend/vendor/doctrine/orm/src/Mapping/MappingException.php
vendored
Normal file
718
backend/vendor/doctrine/orm/src/Mapping/MappingException.php
vendored
Normal file
@@ -0,0 +1,718 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use BackedEnum;
|
||||
use Doctrine\ORM\Exception\ORMException;
|
||||
use Doctrine\Persistence\Mapping\MappingException as PersistenceMappingException;
|
||||
use LibXMLError;
|
||||
use ReflectionException;
|
||||
use ValueError;
|
||||
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function array_values;
|
||||
use function get_debug_type;
|
||||
use function get_parent_class;
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
|
||||
use const PHP_EOL;
|
||||
|
||||
/**
|
||||
* A MappingException indicates that something is wrong with the mapping setup.
|
||||
*/
|
||||
class MappingException extends PersistenceMappingException implements ORMException
|
||||
{
|
||||
/** @param class-string $entityName */
|
||||
public static function identifierRequired(string $entityName): self
|
||||
{
|
||||
$parent = get_parent_class($entityName);
|
||||
if ($parent !== false) {
|
||||
return new self(sprintf(
|
||||
'No identifier/primary key specified for Entity "%s" sub class of "%s". Every Entity must have an identifier/primary key.',
|
||||
$entityName,
|
||||
$parent,
|
||||
));
|
||||
}
|
||||
|
||||
return new self(sprintf(
|
||||
'No identifier/primary key specified for Entity "%s". Every Entity must have an identifier/primary key.',
|
||||
$entityName,
|
||||
));
|
||||
}
|
||||
|
||||
public static function invalidAssociationType(string $entityName, string $fieldName, int $type): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The association "%s#%s" must be of type "ClassMetadata::ONE_TO_MANY", "ClassMetadata::MANY_TO_MANY" or "ClassMetadata::MANY_TO_ONE", "%d" given.',
|
||||
$entityName,
|
||||
$fieldName,
|
||||
$type,
|
||||
));
|
||||
}
|
||||
|
||||
public static function invalidInheritanceType(string $entityName, int $type): self
|
||||
{
|
||||
return new self(sprintf("The inheritance type '%s' specified for '%s' does not exist.", $type, $entityName));
|
||||
}
|
||||
|
||||
public static function generatorNotAllowedWithCompositeId(): self
|
||||
{
|
||||
return new self("Id generators can't be used with a composite id.");
|
||||
}
|
||||
|
||||
public static function missingFieldName(string $entity): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"The field or association mapping misses the 'fieldName' attribute in entity '%s'.",
|
||||
$entity,
|
||||
));
|
||||
}
|
||||
|
||||
public static function missingTargetEntity(string $fieldName): self
|
||||
{
|
||||
return new self(sprintf("The association mapping '%s' misses the 'targetEntity' attribute.", $fieldName));
|
||||
}
|
||||
|
||||
public static function missingSourceEntity(string $fieldName): self
|
||||
{
|
||||
return new self(sprintf("The association mapping '%s' misses the 'sourceEntity' attribute.", $fieldName));
|
||||
}
|
||||
|
||||
public static function missingEmbeddedClass(string $fieldName): self
|
||||
{
|
||||
return new self(sprintf("The embed mapping '%s' misses the 'class' attribute.", $fieldName));
|
||||
}
|
||||
|
||||
public static function mappingFileNotFound(string $entityName, string $fileName): self
|
||||
{
|
||||
return new self(sprintf("No mapping file found named '%s' for class '%s'.", $fileName, $entityName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception for invalid property name override.
|
||||
*
|
||||
* @param string $className The entity's name.
|
||||
*/
|
||||
public static function invalidOverrideFieldName(string $className, string $fieldName): self
|
||||
{
|
||||
return new self(sprintf("Invalid field override named '%s' for class '%s'.", $fieldName, $className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception for invalid property type override.
|
||||
*
|
||||
* @param string $className The entity's name.
|
||||
*/
|
||||
public static function invalidOverrideFieldType(string $className, string $fieldName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"The column type of attribute '%s' on class '%s' could not be changed.",
|
||||
$fieldName,
|
||||
$className,
|
||||
));
|
||||
}
|
||||
|
||||
public static function mappingNotFound(string $className, string $fieldName): self
|
||||
{
|
||||
return new self(sprintf("No mapping found for field '%s' on class '%s'.", $fieldName, $className));
|
||||
}
|
||||
|
||||
public static function queryNotFound(string $className, string $queryName): self
|
||||
{
|
||||
return new self(sprintf("No query found named '%s' on class '%s'.", $queryName, $className));
|
||||
}
|
||||
|
||||
public static function resultMappingNotFound(string $className, string $resultName): self
|
||||
{
|
||||
return new self(sprintf("No result set mapping found named '%s' on class '%s'.", $resultName, $className));
|
||||
}
|
||||
|
||||
public static function emptyQueryMapping(string $entity, string $queryName): self
|
||||
{
|
||||
return new self(sprintf('Query named "%s" in "%s" could not be empty.', $queryName, $entity));
|
||||
}
|
||||
|
||||
public static function nameIsMandatoryForQueryMapping(string $className): self
|
||||
{
|
||||
return new self(sprintf("Query name on entity class '%s' is not defined.", $className));
|
||||
}
|
||||
|
||||
public static function missingQueryMapping(string $entity, string $queryName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Query named "%s" in "%s requires a result class or result set mapping.',
|
||||
$queryName,
|
||||
$entity,
|
||||
));
|
||||
}
|
||||
|
||||
public static function missingResultSetMappingEntity(string $entity, string $resultName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Result set mapping named "%s" in "%s requires a entity class name.',
|
||||
$resultName,
|
||||
$entity,
|
||||
));
|
||||
}
|
||||
|
||||
public static function missingResultSetMappingFieldName(string $entity, string $resultName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Result set mapping named "%s" in "%s requires a field name.',
|
||||
$resultName,
|
||||
$entity,
|
||||
));
|
||||
}
|
||||
|
||||
public static function oneToManyRequiresMappedBy(string $entityName, string $fieldName): MappingException
|
||||
{
|
||||
return new self(sprintf(
|
||||
"OneToMany mapping on entity '%s' field '%s' requires the 'mappedBy' attribute.",
|
||||
$entityName,
|
||||
$fieldName,
|
||||
));
|
||||
}
|
||||
|
||||
public static function joinTableRequired(string $fieldName): self
|
||||
{
|
||||
return new self(sprintf("The mapping of field '%s' requires the 'joinTable' attribute.", $fieldName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called if a required option was not found but is required
|
||||
*
|
||||
* @param string $field Which field cannot be processed?
|
||||
* @param string $expectedOption Which option is required
|
||||
* @param string $hint Can optionally be used to supply a tip for common mistakes,
|
||||
* e.g. "Did you think of the plural s?"
|
||||
*/
|
||||
public static function missingRequiredOption(string $field, string $expectedOption, string $hint = ''): self
|
||||
{
|
||||
$message = "The mapping of field '" . $field . "' is invalid: The option '" . $expectedOption . "' is required.";
|
||||
|
||||
if (! empty($hint)) {
|
||||
$message .= ' (Hint: ' . $hint . ')';
|
||||
}
|
||||
|
||||
return new self($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic exception for invalid mappings.
|
||||
*/
|
||||
public static function invalidMapping(string $fieldName): self
|
||||
{
|
||||
return new self(sprintf("The mapping of field '%s' is invalid.", $fieldName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception for reflection exceptions - adds the entity name,
|
||||
* because there might be long classnames that will be shortened
|
||||
* within the stacktrace
|
||||
*
|
||||
* @param string $entity The entity's name
|
||||
*/
|
||||
public static function reflectionFailure(string $entity, ReflectionException $previousException): self
|
||||
{
|
||||
return new self(sprintf('An error occurred in %s', $entity), 0, $previousException);
|
||||
}
|
||||
|
||||
public static function joinColumnMustPointToMappedField(string $className, string $joinColumn): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The column %s must be mapped to a field in class %s since it is referenced by a join column of another class.',
|
||||
$joinColumn,
|
||||
$className,
|
||||
));
|
||||
}
|
||||
|
||||
public static function joinColumnNotAllowedOnOneToOneInverseSide(string $className, string $fieldName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'%s#%s is a OneToOne inverse side, which does not allow join columns.',
|
||||
$className,
|
||||
$fieldName,
|
||||
));
|
||||
}
|
||||
|
||||
/** @param class-string $className */
|
||||
public static function classIsNotAValidEntityOrMappedSuperClass(string $className): self
|
||||
{
|
||||
$parent = get_parent_class($className);
|
||||
if ($parent !== false) {
|
||||
return new self(sprintf(
|
||||
'Class "%s" sub class of "%s" is not a valid entity or mapped super class.',
|
||||
$className,
|
||||
$parent,
|
||||
));
|
||||
}
|
||||
|
||||
return new self(sprintf(
|
||||
'Class "%s" is not a valid entity or mapped super class.',
|
||||
$className,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entity The entity's name.
|
||||
* @param string $fieldName The name of the field that was already declared.
|
||||
*/
|
||||
public static function duplicateFieldMapping(string $entity, string $fieldName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Property "%s" in "%s" was already declared, but it must be declared only once',
|
||||
$fieldName,
|
||||
$entity,
|
||||
));
|
||||
}
|
||||
|
||||
public static function duplicateAssociationMapping(string $entity, string $fieldName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Property "%s" in "%s" was already declared, but it must be declared only once',
|
||||
$fieldName,
|
||||
$entity,
|
||||
));
|
||||
}
|
||||
|
||||
public static function duplicateQueryMapping(string $entity, string $queryName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Query named "%s" in "%s" was already declared, but it must be declared only once',
|
||||
$queryName,
|
||||
$entity,
|
||||
));
|
||||
}
|
||||
|
||||
public static function duplicateResultSetMapping(string $entity, string $resultName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Result set mapping named "%s" in "%s" was already declared, but it must be declared only once',
|
||||
$resultName,
|
||||
$entity,
|
||||
));
|
||||
}
|
||||
|
||||
public static function singleIdNotAllowedOnCompositePrimaryKey(string $entity): self
|
||||
{
|
||||
return new self('Single id is not allowed on composite primary key in entity ' . $entity);
|
||||
}
|
||||
|
||||
public static function noIdDefined(string $entity): self
|
||||
{
|
||||
return new self('No ID defined for entity ' . $entity);
|
||||
}
|
||||
|
||||
public static function unsupportedOptimisticLockingType(string $entity, string $fieldName, string $unsupportedType): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Locking type "%s" (specified in "%s", field "%s") is not supported by Doctrine.',
|
||||
$unsupportedType,
|
||||
$entity,
|
||||
$fieldName,
|
||||
));
|
||||
}
|
||||
|
||||
public static function fileMappingDriversRequireConfiguredDirectoryPath(string|null $path = null): self
|
||||
{
|
||||
if (! empty($path)) {
|
||||
$path = '[' . $path . ']';
|
||||
}
|
||||
|
||||
return new self(
|
||||
'File mapping drivers must have a valid directory path, ' .
|
||||
'however the given path ' . $path . ' seems to be incorrect!',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an exception that indicates that discriminator entries used in a discriminator map
|
||||
* does not exist in the backed enum provided by enumType option.
|
||||
*
|
||||
* @param array<int,int|string> $entries The discriminator entries that could not be found.
|
||||
* @param string $owningClass The class that declares the discriminator map.
|
||||
* @param string $enumType The enum that entries were checked against.
|
||||
*/
|
||||
public static function invalidEntriesInDiscriminatorMap(array $entries, string $owningClass, string $enumType): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"The entries %s in the discriminator map of class '%s' do not correspond to enum cases of '%s'.",
|
||||
implode(', ', array_map(static fn ($entry): string => sprintf("'%s'", $entry), $entries)),
|
||||
$owningClass,
|
||||
$enumType,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an exception that indicates that a class used in a discriminator map does not exist.
|
||||
* An example would be an outdated (maybe renamed) classname.
|
||||
*
|
||||
* @param string $className The class that could not be found
|
||||
* @param string $owningClass The class that declares the discriminator map.
|
||||
*/
|
||||
public static function invalidClassInDiscriminatorMap(string $className, string $owningClass): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"Entity class '%s' used in the discriminator map of class '%s' " .
|
||||
'does not exist.',
|
||||
$className,
|
||||
$owningClass,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $entries
|
||||
* @param array<string,string> $map
|
||||
*/
|
||||
public static function duplicateDiscriminatorEntry(string $className, array $entries, array $map): self
|
||||
{
|
||||
return new self(
|
||||
'The entries ' . implode(', ', $entries) . " in discriminator map of class '" . $className . "' is duplicated. " .
|
||||
'If the discriminator map is automatically generated you have to convert it to an explicit discriminator map now. ' .
|
||||
'The entries of the current map are: @DiscriminatorMap({' . implode(', ', array_map(
|
||||
static fn ($a, $b) => sprintf("'%s': '%s'", $a, $b),
|
||||
array_keys($map),
|
||||
array_values($map),
|
||||
)) . '})',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $rootEntityClass
|
||||
* @param class-string $childEntityClass
|
||||
*/
|
||||
public static function missingInheritanceTypeDeclaration(string $rootEntityClass, string $childEntityClass): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"Entity class '%s' is a subclass of the root entity class '%s', but no inheritance mapping type was declared.",
|
||||
$childEntityClass,
|
||||
$rootEntityClass,
|
||||
));
|
||||
}
|
||||
|
||||
public static function missingDiscriminatorMap(string $className): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"Entity class '%s' is using inheritance but no discriminator map was defined.",
|
||||
$className,
|
||||
));
|
||||
}
|
||||
|
||||
public static function missingDiscriminatorColumn(string $className): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"Entity class '%s' is using inheritance but no discriminator column was defined.",
|
||||
$className,
|
||||
));
|
||||
}
|
||||
|
||||
public static function invalidDiscriminatorColumnType(string $className, string $type): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"Discriminator column type on entity class '%s' is not allowed to be '%s'. 'string' or 'integer' type variables are suggested!",
|
||||
$className,
|
||||
$type,
|
||||
));
|
||||
}
|
||||
|
||||
public static function nameIsMandatoryForDiscriminatorColumns(string $className): self
|
||||
{
|
||||
return new self(sprintf("Discriminator column name on entity class '%s' is not defined.", $className));
|
||||
}
|
||||
|
||||
public static function cannotVersionIdField(string $className, string $fieldName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"Setting Id field '%s' as versionable in entity class '%s' is not supported.",
|
||||
$fieldName,
|
||||
$className,
|
||||
));
|
||||
}
|
||||
|
||||
public static function duplicateColumnName(string $className, string $columnName): self
|
||||
{
|
||||
return new self("Duplicate definition of column '" . $columnName . "' on entity '" . $className . "' in a field or discriminator column mapping.");
|
||||
}
|
||||
|
||||
public static function illegalToManyAssociationOnMappedSuperclass(string $className, string $field): self
|
||||
{
|
||||
return new self("It is illegal to put an inverse side one-to-many or many-to-many association on mapped superclass '" . $className . '#' . $field . "'.");
|
||||
}
|
||||
|
||||
public static function cannotMapCompositePrimaryKeyEntitiesAsForeignId(string $className, string $targetEntity, string $targetField): self
|
||||
{
|
||||
return new self("It is not possible to map entity '" . $className . "' with a composite primary key " .
|
||||
"as part of the primary key of another entity '" . $targetEntity . '#' . $targetField . "'.");
|
||||
}
|
||||
|
||||
public static function noSingleAssociationJoinColumnFound(string $className, string $field): self
|
||||
{
|
||||
return new self(sprintf("'%s#%s' is not an association with a single join column.", $className, $field));
|
||||
}
|
||||
|
||||
public static function noFieldNameFoundForColumn(string $className, string $column): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"Cannot find a field on '%s' that is mapped to column '%s'. Either the " .
|
||||
'field does not exist or an association exists but it has multiple join columns.',
|
||||
$className,
|
||||
$column,
|
||||
));
|
||||
}
|
||||
|
||||
public static function illegalOrphanRemovalOnIdentifierAssociation(string $className, string $field): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"The orphan removal option is not allowed on an association that is part of the identifier in '%s#%s'.",
|
||||
$className,
|
||||
$field,
|
||||
));
|
||||
}
|
||||
|
||||
public static function illegalOrphanRemoval(string $className, string $field): self
|
||||
{
|
||||
return new self('Orphan removal is only allowed on one-to-one and one-to-many ' .
|
||||
'associations, but ' . $className . '#' . $field . ' is not.');
|
||||
}
|
||||
|
||||
public static function illegalInverseIdentifierAssociation(string $className, string $field): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"An inverse association is not allowed to be identifier in '%s#%s'.",
|
||||
$className,
|
||||
$field,
|
||||
));
|
||||
}
|
||||
|
||||
public static function illegalToManyIdentifierAssociation(string $className, string $field): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"Many-to-many or one-to-many associations are not allowed to be identifier in '%s#%s'.",
|
||||
$className,
|
||||
$field,
|
||||
));
|
||||
}
|
||||
|
||||
public static function noInheritanceOnMappedSuperClass(string $className): self
|
||||
{
|
||||
return new self("It is not supported to define inheritance information on a mapped superclass '" . $className . "'.");
|
||||
}
|
||||
|
||||
public static function mappedClassNotPartOfDiscriminatorMap(string $className, string $rootClassName): self
|
||||
{
|
||||
return new self(
|
||||
"Entity '" . $className . "' has to be part of the discriminator map of '" . $rootClassName . "' " .
|
||||
"to be properly mapped in the inheritance hierarchy. Alternatively you can make '" . $className . "' an abstract class " .
|
||||
'to avoid this exception from occurring.',
|
||||
);
|
||||
}
|
||||
|
||||
public static function lifecycleCallbackMethodNotFound(string $className, string $methodName): self
|
||||
{
|
||||
return new self("Entity '" . $className . "' has no method '" . $methodName . "' to be registered as lifecycle callback.");
|
||||
}
|
||||
|
||||
/** @param class-string $className */
|
||||
public static function illegalLifecycleCallbackOnEmbeddedClass(string $event, string $className): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
<<<'EXCEPTION'
|
||||
Context: Attempt to register lifecycle callback "%s" on embedded class "%s".
|
||||
Problem: Registering lifecycle callbacks on embedded classes is not allowed.
|
||||
EXCEPTION,
|
||||
$event,
|
||||
$className,
|
||||
));
|
||||
}
|
||||
|
||||
public static function entityListenerClassNotFound(string $listenerName, string $className): self
|
||||
{
|
||||
return new self(sprintf('Entity Listener "%s" declared on "%s" not found.', $listenerName, $className));
|
||||
}
|
||||
|
||||
public static function entityListenerMethodNotFound(string $listenerName, string $methodName, string $className): self
|
||||
{
|
||||
return new self(sprintf('Entity Listener "%s" declared on "%s" has no method "%s".', $listenerName, $className, $methodName));
|
||||
}
|
||||
|
||||
public static function duplicateEntityListener(string $listenerName, string $methodName, string $className): self
|
||||
{
|
||||
return new self(sprintf('Entity Listener "%s#%s()" in "%s" was already declared, but it must be declared only once.', $listenerName, $methodName, $className));
|
||||
}
|
||||
|
||||
/** @param class-string $className */
|
||||
public static function invalidFetchMode(string $className, string $fetchMode): self
|
||||
{
|
||||
return new self("Entity '" . $className . "' has a mapping with invalid fetch mode '" . $fetchMode . "'");
|
||||
}
|
||||
|
||||
public static function invalidGeneratedMode(int|string $generatedMode): self
|
||||
{
|
||||
return new self("Invalid generated mode '" . $generatedMode . "'");
|
||||
}
|
||||
|
||||
public static function compositeKeyAssignedIdGeneratorRequired(string $className): self
|
||||
{
|
||||
return new self("Entity '" . $className . "' has a composite identifier but uses an ID generator other than manually assigning (Identity, Sequence). This is not supported.");
|
||||
}
|
||||
|
||||
public static function invalidTargetEntityClass(string $targetEntity, string $sourceEntity, string $associationName): self
|
||||
{
|
||||
return new self('The target-entity ' . $targetEntity . " cannot be found in '" . $sourceEntity . '#' . $associationName . "'.");
|
||||
}
|
||||
|
||||
/** @param string[] $cascades */
|
||||
public static function invalidCascadeOption(array $cascades, string $className, string $propertyName): self
|
||||
{
|
||||
$cascades = implode(', ', array_map(static fn (string $e): string => "'" . $e . "'", $cascades));
|
||||
|
||||
return new self(sprintf(
|
||||
"You have specified invalid cascade options for %s::$%s: %s; available options: 'remove', 'persist', 'refresh', and 'detach'",
|
||||
$className,
|
||||
$propertyName,
|
||||
$cascades,
|
||||
));
|
||||
}
|
||||
|
||||
public static function missingSequenceName(string $className): self
|
||||
{
|
||||
return new self(
|
||||
sprintf('Missing "sequenceName" attribute for sequence id generator definition on class "%s".', $className),
|
||||
);
|
||||
}
|
||||
|
||||
public static function infiniteEmbeddableNesting(string $className, string $propertyName): self
|
||||
{
|
||||
return new self(
|
||||
sprintf(
|
||||
'Infinite nesting detected for embedded property %s::%s. ' .
|
||||
'You cannot embed an embeddable from the same type inside an embeddable.',
|
||||
$className,
|
||||
$propertyName,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public static function illegalOverrideOfInheritedProperty(string $className, string $propertyName, string $inheritFromClass): self
|
||||
{
|
||||
return new self(
|
||||
sprintf(
|
||||
'Overrides are only allowed for fields or associations declared in mapped superclasses or traits. This is not the case for %s::%s, which was inherited from %s.',
|
||||
$className,
|
||||
$propertyName,
|
||||
$inheritFromClass,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public static function invalidIndexConfiguration(string $className, string $indexName): self
|
||||
{
|
||||
return new self(
|
||||
sprintf(
|
||||
'Index %s for entity %s should contain columns or fields values, but not both.',
|
||||
$indexName,
|
||||
$className,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public static function invalidUniqueConstraintConfiguration(string $className, string $indexName): self
|
||||
{
|
||||
return new self(
|
||||
sprintf(
|
||||
'Unique constraint %s for entity %s should contain columns or fields values, but not both.',
|
||||
$indexName,
|
||||
$className,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public static function invalidOverrideType(string $expectdType, mixed $givenValue): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Expected %s, but %s was given.',
|
||||
$expectdType,
|
||||
get_debug_type($givenValue),
|
||||
));
|
||||
}
|
||||
|
||||
public static function backedEnumTypeRequired(string $className, string $fieldName, string $enumType): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Attempting to map a non-backed enum type %s in entity %s::$%s. Please use backed enums only',
|
||||
$enumType,
|
||||
$className,
|
||||
$fieldName,
|
||||
));
|
||||
}
|
||||
|
||||
public static function nonEnumTypeMapped(string $className, string $fieldName, string $enumType): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Attempting to map non-enum type %s as enum in entity %s::$%s',
|
||||
$enumType,
|
||||
$className,
|
||||
$fieldName,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $className
|
||||
* @param class-string<BackedEnum> $enumType
|
||||
*/
|
||||
public static function invalidEnumValue(
|
||||
string $className,
|
||||
string $fieldName,
|
||||
string $value,
|
||||
string $enumType,
|
||||
ValueError $previous,
|
||||
): self {
|
||||
return new self(sprintf(
|
||||
<<<'EXCEPTION'
|
||||
Context: Trying to hydrate enum property "%s::$%s"
|
||||
Problem: Case "%s" is not listed in enum "%s"
|
||||
Solution: Either add the case to the enum type or migrate the database column to use another case of the enum
|
||||
EXCEPTION
|
||||
,
|
||||
$className,
|
||||
$fieldName,
|
||||
$value,
|
||||
$enumType,
|
||||
), 0, $previous);
|
||||
}
|
||||
|
||||
/** @param LibXMLError[] $errors */
|
||||
public static function fromLibXmlErrors(array $errors): self
|
||||
{
|
||||
$formatter = static fn (LibXMLError $error): string => sprintf(
|
||||
'libxml error: %s in %s at line %d',
|
||||
$error->message,
|
||||
$error->file,
|
||||
$error->line,
|
||||
);
|
||||
|
||||
return new self(implode(PHP_EOL, array_map($formatter, $errors)));
|
||||
}
|
||||
|
||||
public static function invalidAttributeOnEmbeddable(string $entityName, string $attributeName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Attribute "%s" on embeddable "%s" is not allowed.',
|
||||
$attributeName,
|
||||
$entityName,
|
||||
));
|
||||
}
|
||||
|
||||
public static function mappingVirtualPropertyNotAllowed(string $entityName, string $propertyName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Mapping virtual property "%s" on entity "%s" is not allowed.',
|
||||
$propertyName,
|
||||
$entityName,
|
||||
));
|
||||
}
|
||||
}
|
||||
71
backend/vendor/doctrine/orm/src/Mapping/NamingStrategy.php
vendored
Normal file
71
backend/vendor/doctrine/orm/src/Mapping/NamingStrategy.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* A set of rules for determining the physical column and table names
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
*/
|
||||
interface NamingStrategy
|
||||
{
|
||||
/**
|
||||
* Returns a table name for an entity class.
|
||||
*
|
||||
* @param class-string $className
|
||||
*/
|
||||
public function classToTableName(string $className): string;
|
||||
|
||||
/**
|
||||
* Returns a column name for a property.
|
||||
*
|
||||
* @param class-string $className
|
||||
*/
|
||||
public function propertyToColumnName(string $propertyName, string $className): string;
|
||||
|
||||
/**
|
||||
* Returns a column name for an embedded property.
|
||||
*
|
||||
* @param class-string $className
|
||||
* @param class-string $embeddedClassName
|
||||
*/
|
||||
public function embeddedFieldToColumnName(
|
||||
string $propertyName,
|
||||
string $embeddedColumnName,
|
||||
string $className,
|
||||
string $embeddedClassName,
|
||||
): string;
|
||||
|
||||
/**
|
||||
* Returns the default reference column name.
|
||||
*/
|
||||
public function referenceColumnName(): string;
|
||||
|
||||
/**
|
||||
* Returns a join column name for a property.
|
||||
*
|
||||
* @param class-string $className
|
||||
*/
|
||||
public function joinColumnName(string $propertyName, string $className): string;
|
||||
|
||||
/**
|
||||
* Returns a join table name.
|
||||
*
|
||||
* @param class-string $sourceEntity
|
||||
* @param class-string $targetEntity
|
||||
*/
|
||||
public function joinTableName(string $sourceEntity, string $targetEntity, string $propertyName): string;
|
||||
|
||||
/**
|
||||
* Returns the foreign key column name for the given parameters.
|
||||
*
|
||||
* @param class-string $entityName An entity.
|
||||
* @param string|null $referencedColumnName A property name or null in
|
||||
* case of a self-referencing
|
||||
* entity with join columns
|
||||
* defined in the mapping
|
||||
*/
|
||||
public function joinKeyColumnName(string $entityName, string|null $referencedColumnName): string;
|
||||
}
|
||||
26
backend/vendor/doctrine/orm/src/Mapping/OneToMany.php
vendored
Normal file
26
backend/vendor/doctrine/orm/src/Mapping/OneToMany.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class OneToMany implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* @param class-string|null $targetEntity
|
||||
* @param string[]|null $cascade
|
||||
* @phpstan-param 'LAZY'|'EAGER'|'EXTRA_LAZY' $fetch
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string|null $targetEntity = null,
|
||||
public readonly string|null $mappedBy = null,
|
||||
public readonly array|null $cascade = null,
|
||||
public readonly string $fetch = 'LAZY',
|
||||
public readonly bool $orphanRemoval = false,
|
||||
public readonly string|null $indexBy = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
75
backend/vendor/doctrine/orm/src/Mapping/OneToManyAssociationMapping.php
vendored
Normal file
75
backend/vendor/doctrine/orm/src/Mapping/OneToManyAssociationMapping.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
final class OneToManyAssociationMapping extends ToManyInverseSideMapping
|
||||
{
|
||||
/**
|
||||
* @param mixed[] $mappingArray
|
||||
* @phpstan-param array{
|
||||
* fieldName: string,
|
||||
* sourceEntity: class-string,
|
||||
* targetEntity: class-string,
|
||||
* cascade?: list<'persist'|'remove'|'detach'|'refresh'|'all'>,
|
||||
* fetch?: ClassMetadata::FETCH_*|null,
|
||||
* inherited?: class-string|null,
|
||||
* declared?: class-string|null,
|
||||
* cache?: array<mixed>|null,
|
||||
* id?: bool|null,
|
||||
* isOnDeleteCascade?: bool|null,
|
||||
* originalClass?: class-string|null,
|
||||
* originalField?: string|null,
|
||||
* orphanRemoval?: bool,
|
||||
* unique?: bool|null,
|
||||
* joinTable?: mixed[]|null,
|
||||
* type?: int,
|
||||
* isOwningSide: bool,
|
||||
* } $mappingArray
|
||||
*/
|
||||
public static function fromMappingArray(array $mappingArray): static
|
||||
{
|
||||
$mapping = parent::fromMappingArray($mappingArray);
|
||||
|
||||
if ($mapping->orphanRemoval && ! $mapping->isCascadeRemove()) {
|
||||
$mapping->cascade[] = 'remove';
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $mappingArray
|
||||
* @phpstan-param array{
|
||||
* fieldName: string,
|
||||
* sourceEntity: class-string,
|
||||
* targetEntity: class-string,
|
||||
* cascade?: list<'persist'|'remove'|'detach'|'refresh'|'all'>,
|
||||
* fetch?: ClassMetadata::FETCH_*|null,
|
||||
* inherited?: class-string|null,
|
||||
* declared?: class-string|null,
|
||||
* cache?: array<mixed>|null,
|
||||
* id?: bool|null,
|
||||
* isOnDeleteCascade?: bool|null,
|
||||
* originalClass?: class-string|null,
|
||||
* originalField?: string|null,
|
||||
* orphanRemoval?: bool,
|
||||
* unique?: bool|null,
|
||||
* joinTable?: mixed[]|null,
|
||||
* type?: int,
|
||||
* isOwningSide: bool,
|
||||
* } $mappingArray
|
||||
*/
|
||||
public static function fromMappingArrayAndName(array $mappingArray, string $name): static
|
||||
{
|
||||
$mapping = self::fromMappingArray($mappingArray);
|
||||
|
||||
// OneToMany-side MUST be inverse (must have mappedBy)
|
||||
if (! isset($mapping->mappedBy)) {
|
||||
throw MappingException::oneToManyRequiresMappedBy($name, $mapping->fieldName);
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
}
|
||||
26
backend/vendor/doctrine/orm/src/Mapping/OneToOne.php
vendored
Normal file
26
backend/vendor/doctrine/orm/src/Mapping/OneToOne.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class OneToOne implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* @param class-string|null $targetEntity
|
||||
* @param array<string>|null $cascade
|
||||
* @phpstan-param 'LAZY'|'EAGER'|'EXTRA_LAZY' $fetch
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string|null $targetEntity = null,
|
||||
public readonly string|null $mappedBy = null,
|
||||
public readonly string|null $inversedBy = null,
|
||||
public readonly array|null $cascade = null,
|
||||
public readonly string $fetch = 'LAZY',
|
||||
public readonly bool $orphanRemoval = false,
|
||||
) {
|
||||
}
|
||||
}
|
||||
9
backend/vendor/doctrine/orm/src/Mapping/OneToOneAssociationMapping.php
vendored
Normal file
9
backend/vendor/doctrine/orm/src/Mapping/OneToOneAssociationMapping.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
interface OneToOneAssociationMapping extends ToOneAssociationMapping
|
||||
{
|
||||
}
|
||||
9
backend/vendor/doctrine/orm/src/Mapping/OneToOneInverseSideMapping.php
vendored
Normal file
9
backend/vendor/doctrine/orm/src/Mapping/OneToOneInverseSideMapping.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
final class OneToOneInverseSideMapping extends ToOneInverseSideMapping implements OneToOneAssociationMapping
|
||||
{
|
||||
}
|
||||
9
backend/vendor/doctrine/orm/src/Mapping/OneToOneOwningSideMapping.php
vendored
Normal file
9
backend/vendor/doctrine/orm/src/Mapping/OneToOneOwningSideMapping.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
final class OneToOneOwningSideMapping extends ToOneOwningSideMapping implements OneToOneAssociationMapping
|
||||
{
|
||||
}
|
||||
17
backend/vendor/doctrine/orm/src/Mapping/OrderBy.php
vendored
Normal file
17
backend/vendor/doctrine/orm/src/Mapping/OrderBy.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class OrderBy implements MappingAttribute
|
||||
{
|
||||
/** @param array<string> $value */
|
||||
public function __construct(
|
||||
public readonly array $value,
|
||||
) {
|
||||
}
|
||||
}
|
||||
28
backend/vendor/doctrine/orm/src/Mapping/OwningSideMapping.php
vendored
Normal file
28
backend/vendor/doctrine/orm/src/Mapping/OwningSideMapping.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
abstract class OwningSideMapping extends AssociationMapping
|
||||
{
|
||||
/**
|
||||
* required for bidirectional associations
|
||||
* The name of the field that completes the bidirectional association on
|
||||
* the inverse side. This key must be specified on the owning side of a
|
||||
* bidirectional association.
|
||||
*/
|
||||
public string|null $inversedBy = null;
|
||||
|
||||
/** @return list<string> */
|
||||
public function __sleep(): array
|
||||
{
|
||||
$serialized = parent::__sleep();
|
||||
|
||||
if ($this->inversedBy !== null) {
|
||||
$serialized[] = 'inversedBy';
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/PostLoad.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/PostLoad.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
final class PostLoad implements MappingAttribute
|
||||
{
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/PostPersist.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/PostPersist.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
final class PostPersist implements MappingAttribute
|
||||
{
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/PostRemove.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/PostRemove.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
final class PostRemove implements MappingAttribute
|
||||
{
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/PostUpdate.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/PostUpdate.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
final class PostUpdate implements MappingAttribute
|
||||
{
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/PreFlush.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/PreFlush.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
final class PreFlush implements MappingAttribute
|
||||
{
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/PrePersist.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/PrePersist.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
final class PrePersist implements MappingAttribute
|
||||
{
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/PreRemove.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/PreRemove.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
final class PreRemove implements MappingAttribute
|
||||
{
|
||||
}
|
||||
12
backend/vendor/doctrine/orm/src/Mapping/PreUpdate.php
vendored
Normal file
12
backend/vendor/doctrine/orm/src/Mapping/PreUpdate.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
final class PreUpdate implements MappingAttribute
|
||||
{
|
||||
}
|
||||
53
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/EmbeddablePropertyAccessor.php
vendored
Normal file
53
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/EmbeddablePropertyAccessor.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\PropertyAccessors;
|
||||
|
||||
use Doctrine\Instantiator\Instantiator;
|
||||
use ReflectionProperty;
|
||||
|
||||
/** @internal */
|
||||
class EmbeddablePropertyAccessor implements PropertyAccessor
|
||||
{
|
||||
private static Instantiator|null $instantiator = null;
|
||||
|
||||
public function __construct(
|
||||
private PropertyAccessor $parent,
|
||||
private PropertyAccessor $child,
|
||||
/** @var class-string */
|
||||
private string $embeddedClass,
|
||||
) {
|
||||
}
|
||||
|
||||
public function setValue(object $object, mixed $value): void
|
||||
{
|
||||
$embeddedObject = $this->parent->getValue($object);
|
||||
|
||||
if ($embeddedObject === null) {
|
||||
self::$instantiator ??= new Instantiator();
|
||||
|
||||
$embeddedObject = self::$instantiator->instantiate($this->embeddedClass);
|
||||
|
||||
$this->parent->setValue($object, $embeddedObject);
|
||||
}
|
||||
|
||||
$this->child->setValue($embeddedObject, $value);
|
||||
}
|
||||
|
||||
public function getValue(object $object): mixed
|
||||
{
|
||||
$embeddedObject = $this->parent->getValue($object);
|
||||
|
||||
if ($embeddedObject === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->child->getValue($embeddedObject);
|
||||
}
|
||||
|
||||
public function getUnderlyingReflector(): ReflectionProperty
|
||||
{
|
||||
return $this->child->getUnderlyingReflector();
|
||||
}
|
||||
}
|
||||
85
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/EnumPropertyAccessor.php
vendored
Normal file
85
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/EnumPropertyAccessor.php
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\PropertyAccessors;
|
||||
|
||||
use BackedEnum;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function array_map;
|
||||
use function is_array;
|
||||
use function reset;
|
||||
|
||||
/** @internal */
|
||||
class EnumPropertyAccessor implements PropertyAccessor
|
||||
{
|
||||
/** @param class-string<BackedEnum> $enumType */
|
||||
public function __construct(private PropertyAccessor $parent, private string $enumType)
|
||||
{
|
||||
}
|
||||
|
||||
public function setValue(object $object, mixed $value): void
|
||||
{
|
||||
if ($value !== null) {
|
||||
$value = $this->toEnum($value);
|
||||
}
|
||||
|
||||
$this->parent->setValue($object, $value);
|
||||
}
|
||||
|
||||
public function getValue(object $object): mixed
|
||||
{
|
||||
$enum = $this->parent->getValue($object);
|
||||
|
||||
if ($enum === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->fromEnum($enum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BackedEnum|BackedEnum[] $enum
|
||||
*
|
||||
* @return ($enum is BackedEnum ? (string|int) : (string[]|int[]))
|
||||
*/
|
||||
private function fromEnum($enum) // phpcs:ignore
|
||||
{
|
||||
if (is_array($enum)) {
|
||||
return array_map(static function (BackedEnum $enum) {
|
||||
return $enum->value;
|
||||
}, $enum);
|
||||
}
|
||||
|
||||
return $enum->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param BackedEnum|BackedEnum[]|int|string|int[]|string[] $value
|
||||
*
|
||||
* @return ($value is int|string|BackedEnum ? BackedEnum : BackedEnum[])
|
||||
*/
|
||||
private function toEnum($value): BackedEnum|array
|
||||
{
|
||||
if ($value instanceof BackedEnum) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
$v = reset($value);
|
||||
if ($v instanceof BackedEnum) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return array_map([$this->enumType, 'from'], $value);
|
||||
}
|
||||
|
||||
return $this->enumType::from($value);
|
||||
}
|
||||
|
||||
public function getUnderlyingReflector(): ReflectionProperty
|
||||
{
|
||||
return $this->parent->getUnderlyingReflector();
|
||||
}
|
||||
}
|
||||
61
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/ObjectCastPropertyAccessor.php
vendored
Normal file
61
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/ObjectCastPropertyAccessor.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\PropertyAccessors;
|
||||
|
||||
use Doctrine\ORM\Proxy\InternalProxy;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function ltrim;
|
||||
|
||||
/** @internal */
|
||||
class ObjectCastPropertyAccessor implements PropertyAccessor
|
||||
{
|
||||
/** @param class-string $class */
|
||||
public static function fromNames(string $class, string $name): self
|
||||
{
|
||||
$reflectionProperty = new ReflectionProperty($class, $name);
|
||||
|
||||
$key = $reflectionProperty->isPrivate() ? "\0" . ltrim($class, '\\') . "\0" . $name : ($reflectionProperty->isProtected() ? "\0*\0" . $name : $name);
|
||||
|
||||
return new self($reflectionProperty, $key);
|
||||
}
|
||||
|
||||
public static function fromReflectionProperty(ReflectionProperty $reflectionProperty): self
|
||||
{
|
||||
$name = $reflectionProperty->getName();
|
||||
$key = $reflectionProperty->isPrivate() ? "\0" . ltrim($reflectionProperty->getDeclaringClass()->getName(), '\\') . "\0" . $name : ($reflectionProperty->isProtected() ? "\0*\0" . $name : $name);
|
||||
|
||||
return new self($reflectionProperty, $key);
|
||||
}
|
||||
|
||||
private function __construct(private ReflectionProperty $reflectionProperty, private string $key)
|
||||
{
|
||||
}
|
||||
|
||||
public function setValue(object $object, mixed $value): void
|
||||
{
|
||||
if (! ($object instanceof InternalProxy && ! $object->__isInitialized())) {
|
||||
$this->reflectionProperty->setValue($object, $value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$object->__setInitialized(true);
|
||||
|
||||
$this->reflectionProperty->setValue($object, $value);
|
||||
|
||||
$object->__setInitialized(false);
|
||||
}
|
||||
|
||||
public function getValue(object $object): mixed
|
||||
{
|
||||
return ((array) $object)[$this->key] ?? null;
|
||||
}
|
||||
|
||||
public function getUnderlyingReflector(): ReflectionProperty
|
||||
{
|
||||
return $this->reflectionProperty;
|
||||
}
|
||||
}
|
||||
27
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/PropertyAccessor.php
vendored
Normal file
27
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/PropertyAccessor.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\PropertyAccessors;
|
||||
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
* A property accessor is a class that allows to read and write properties on objects regardless of visibility.
|
||||
*
|
||||
* We use them while creating objects from database rows in {@link UnitOfWork::createEntity()} or when
|
||||
* computing changesets from objects that are about to be written back to the database in {@link UnitOfWork::computeChangeSet()}.
|
||||
*
|
||||
* This abstraction over ReflectionProperty is necessary, because for several features of either Doctrine or PHP, we
|
||||
* need to handle edge cases in reflection at a central location in the code.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface PropertyAccessor
|
||||
{
|
||||
public function setValue(object $object, mixed $value): void;
|
||||
|
||||
public function getValue(object $object): mixed;
|
||||
|
||||
public function getUnderlyingReflector(): ReflectionProperty;
|
||||
}
|
||||
32
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/PropertyAccessorFactory.php
vendored
Normal file
32
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/PropertyAccessorFactory.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\PropertyAccessors;
|
||||
|
||||
use ReflectionProperty;
|
||||
|
||||
use const PHP_VERSION_ID;
|
||||
|
||||
class PropertyAccessorFactory
|
||||
{
|
||||
/** @phpstan-param class-string $className */
|
||||
public static function createPropertyAccessor(string $className, string $propertyName): PropertyAccessor
|
||||
{
|
||||
$reflectionProperty = new ReflectionProperty($className, $propertyName);
|
||||
|
||||
$accessor = PHP_VERSION_ID >= 80400
|
||||
? RawValuePropertyAccessor::fromReflectionProperty($reflectionProperty)
|
||||
: ObjectCastPropertyAccessor::fromReflectionProperty($reflectionProperty);
|
||||
|
||||
if ($reflectionProperty->hasType() && ! $reflectionProperty->getType()->allowsNull()) {
|
||||
$accessor = new TypedNoDefaultPropertyAccessor($accessor, $reflectionProperty);
|
||||
}
|
||||
|
||||
if ($reflectionProperty->isReadOnly()) {
|
||||
$accessor = new ReadonlyAccessor($accessor, $reflectionProperty);
|
||||
}
|
||||
|
||||
return $accessor;
|
||||
}
|
||||
}
|
||||
63
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/RawValuePropertyAccessor.php
vendored
Normal file
63
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/RawValuePropertyAccessor.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\PropertyAccessors;
|
||||
|
||||
use Doctrine\ORM\Proxy\InternalProxy;
|
||||
use LogicException;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function ltrim;
|
||||
|
||||
use const PHP_VERSION_ID;
|
||||
|
||||
/**
|
||||
* This is a PHP 8.4 and up only class and replaces ObjectCastPropertyAccessor.
|
||||
*
|
||||
* It works based on the raw values of a property, which for a case of property hooks
|
||||
* is the backed value. If we kept using setValue/getValue, this would go through the hooks,
|
||||
* which potentially change the data.
|
||||
*/
|
||||
class RawValuePropertyAccessor implements PropertyAccessor
|
||||
{
|
||||
public static function fromReflectionProperty(ReflectionProperty $reflectionProperty): self
|
||||
{
|
||||
$name = $reflectionProperty->getName();
|
||||
$key = $reflectionProperty->isPrivate() ? "\0" . ltrim($reflectionProperty->getDeclaringClass()->getName(), '\\') . "\0" . $name : ($reflectionProperty->isProtected() ? "\0*\0" . $name : $name);
|
||||
|
||||
return new self($reflectionProperty, $key);
|
||||
}
|
||||
|
||||
private function __construct(private ReflectionProperty $reflectionProperty, private string $key)
|
||||
{
|
||||
if (PHP_VERSION_ID < 80400) {
|
||||
throw new LogicException('This class requires PHP 8.4 or higher.');
|
||||
}
|
||||
}
|
||||
|
||||
public function setValue(object $object, mixed $value): void
|
||||
{
|
||||
if (! ($object instanceof InternalProxy && ! $object->__isInitialized())) {
|
||||
$this->reflectionProperty->setRawValueWithoutLazyInitialization($object, $value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$object->__setInitialized(true);
|
||||
|
||||
$this->reflectionProperty->setRawValue($object, $value);
|
||||
|
||||
$object->__setInitialized(false);
|
||||
}
|
||||
|
||||
public function getValue(object $object): mixed
|
||||
{
|
||||
return ((array) $object)[$this->key] ?? null;
|
||||
}
|
||||
|
||||
public function getUnderlyingReflector(): ReflectionProperty
|
||||
{
|
||||
return $this->reflectionProperty;
|
||||
}
|
||||
}
|
||||
60
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/ReadonlyAccessor.php
vendored
Normal file
60
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/ReadonlyAccessor.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\PropertyAccessors;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
use const PHP_VERSION_ID;
|
||||
|
||||
/** @internal */
|
||||
class ReadonlyAccessor implements PropertyAccessor
|
||||
{
|
||||
public function __construct(private PropertyAccessor $parent, private ReflectionProperty $reflectionProperty)
|
||||
{
|
||||
if (! $this->reflectionProperty->isReadOnly()) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'%s::$%s must be readonly property',
|
||||
$this->reflectionProperty->getDeclaringClass()->getName(),
|
||||
$this->reflectionProperty->getName(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function setValue(object $object, mixed $value): void
|
||||
{
|
||||
/* For lazy properties, skip the isInitialized() check
|
||||
because it would trigger the initialization of the whole object. */
|
||||
if (
|
||||
PHP_VERSION_ID >= 80400 && $this->reflectionProperty->isLazy($object)
|
||||
|| ! $this->reflectionProperty->isInitialized($object)
|
||||
) {
|
||||
$this->parent->setValue($object, $value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->parent->getValue($object) !== $value) {
|
||||
throw new LogicException(sprintf(
|
||||
'Attempting to change readonly property %s::$%s.',
|
||||
$this->reflectionProperty->getDeclaringClass()->getName(),
|
||||
$this->reflectionProperty->getName(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function getValue(object $object): mixed
|
||||
{
|
||||
return $this->parent->getValue($object);
|
||||
}
|
||||
|
||||
public function getUnderlyingReflector(): ReflectionProperty
|
||||
{
|
||||
return $this->reflectionProperty;
|
||||
}
|
||||
}
|
||||
69
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/TypedNoDefaultPropertyAccessor.php
vendored
Normal file
69
backend/vendor/doctrine/orm/src/Mapping/PropertyAccessors/TypedNoDefaultPropertyAccessor.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping\PropertyAccessors;
|
||||
|
||||
use Closure;
|
||||
use InvalidArgumentException;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function assert;
|
||||
use function sprintf;
|
||||
|
||||
/** @internal */
|
||||
class TypedNoDefaultPropertyAccessor implements PropertyAccessor
|
||||
{
|
||||
private Closure|null $unsetter = null;
|
||||
|
||||
public function __construct(private PropertyAccessor $parent, private ReflectionProperty $reflectionProperty)
|
||||
{
|
||||
if (! $this->reflectionProperty->hasType()) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'%s::$%s must have a type when used with TypedNoDefaultPropertyAccessor',
|
||||
$this->reflectionProperty->getDeclaringClass()->getName(),
|
||||
$this->reflectionProperty->getName(),
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->reflectionProperty->getType()->allowsNull()) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'%s::$%s must not be nullable when used with TypedNoDefaultPropertyAccessor',
|
||||
$this->reflectionProperty->getDeclaringClass()->getName(),
|
||||
$this->reflectionProperty->getName(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function setValue(object $object, mixed $value): void
|
||||
{
|
||||
if ($value === null) {
|
||||
if ($this->unsetter === null) {
|
||||
$propertyName = $this->reflectionProperty->getName();
|
||||
$this->unsetter = function () use ($propertyName): void {
|
||||
unset($this->$propertyName);
|
||||
};
|
||||
}
|
||||
|
||||
$unsetter = $this->unsetter->bindTo($object, $this->reflectionProperty->getDeclaringClass()->getName());
|
||||
|
||||
assert($unsetter instanceof Closure);
|
||||
|
||||
$unsetter();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->parent->setValue($object, $value);
|
||||
}
|
||||
|
||||
public function getValue(object $object): mixed
|
||||
{
|
||||
return $this->reflectionProperty->isInitialized($object) ? $this->parent->getValue($object) : null;
|
||||
}
|
||||
|
||||
public function getUnderlyingReflector(): ReflectionProperty
|
||||
{
|
||||
return $this->reflectionProperty;
|
||||
}
|
||||
}
|
||||
68
backend/vendor/doctrine/orm/src/Mapping/QuoteStrategy.php
vendored
Normal file
68
backend/vendor/doctrine/orm/src/Mapping/QuoteStrategy.php
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
|
||||
/**
|
||||
* A set of rules for determining the column, alias and table quotes.
|
||||
*/
|
||||
interface QuoteStrategy
|
||||
{
|
||||
/**
|
||||
* Gets the (possibly quoted) column name for safe use in an SQL statement.
|
||||
*/
|
||||
public function getColumnName(string $fieldName, ClassMetadata $class, AbstractPlatform $platform): string;
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) primary table name for safe use in an SQL statement.
|
||||
*/
|
||||
public function getTableName(ClassMetadata $class, AbstractPlatform $platform): string;
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) sequence name for safe use in an SQL statement.
|
||||
*
|
||||
* @param mixed[] $definition
|
||||
*/
|
||||
public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform): string;
|
||||
|
||||
/** Gets the (possibly quoted) name of the join table. */
|
||||
public function getJoinTableName(
|
||||
ManyToManyOwningSideMapping $association,
|
||||
ClassMetadata $class,
|
||||
AbstractPlatform $platform,
|
||||
): string;
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) join column name.
|
||||
*/
|
||||
public function getJoinColumnName(JoinColumnMapping $joinColumn, ClassMetadata $class, AbstractPlatform $platform): string;
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) join column name.
|
||||
*/
|
||||
public function getReferencedJoinColumnName(
|
||||
JoinColumnMapping $joinColumn,
|
||||
ClassMetadata $class,
|
||||
AbstractPlatform $platform,
|
||||
): string;
|
||||
|
||||
/**
|
||||
* Gets the (possibly quoted) identifier column names for safe use in an SQL statement.
|
||||
*
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform): array;
|
||||
|
||||
/**
|
||||
* Gets the column alias.
|
||||
*/
|
||||
public function getColumnAlias(
|
||||
string $columnName,
|
||||
int $counter,
|
||||
AbstractPlatform $platform,
|
||||
ClassMetadata|null $class = null,
|
||||
): string;
|
||||
}
|
||||
61
backend/vendor/doctrine/orm/src/Mapping/ReflectionEmbeddedProperty.php
vendored
Normal file
61
backend/vendor/doctrine/orm/src/Mapping/ReflectionEmbeddedProperty.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\Instantiator\Instantiator;
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
* Acts as a proxy to a nested Property structure, making it look like
|
||||
* just a single scalar property.
|
||||
*
|
||||
* This way value objects "just work" without UnitOfWork, Persisters or Hydrators
|
||||
* needing any changes.
|
||||
*
|
||||
* TODO: Move this class into Common\Reflection
|
||||
*/
|
||||
final class ReflectionEmbeddedProperty extends ReflectionProperty
|
||||
{
|
||||
private Instantiator|null $instantiator = null;
|
||||
|
||||
/**
|
||||
* @param ReflectionProperty $parentProperty reflection property of the class where the embedded object has to be put
|
||||
* @param ReflectionProperty $childProperty reflection property of the embedded object
|
||||
* @phpstan-param class-string $embeddedClass
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ReflectionProperty $parentProperty,
|
||||
private readonly ReflectionProperty $childProperty,
|
||||
private readonly string $embeddedClass,
|
||||
) {
|
||||
parent::__construct($childProperty->getDeclaringClass()->name, $childProperty->getName());
|
||||
}
|
||||
|
||||
public function getValue(object|null $object = null): mixed
|
||||
{
|
||||
$embeddedObject = $this->parentProperty->getValue($object);
|
||||
|
||||
if ($embeddedObject === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->childProperty->getValue($embeddedObject);
|
||||
}
|
||||
|
||||
public function setValue(mixed $object, mixed $value = null): void
|
||||
{
|
||||
$embeddedObject = $this->parentProperty->getValue($object);
|
||||
|
||||
if ($embeddedObject === null) {
|
||||
$this->instantiator ??= new Instantiator();
|
||||
|
||||
$embeddedObject = $this->instantiator->instantiate($this->embeddedClass);
|
||||
|
||||
$this->parentProperty->setValue($object, $embeddedObject);
|
||||
}
|
||||
|
||||
$this->childProperty->setValue($embeddedObject, $value);
|
||||
}
|
||||
}
|
||||
87
backend/vendor/doctrine/orm/src/Mapping/ReflectionEnumProperty.php
vendored
Normal file
87
backend/vendor/doctrine/orm/src/Mapping/ReflectionEnumProperty.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use BackedEnum;
|
||||
use ReflectionProperty;
|
||||
use ValueError;
|
||||
|
||||
use function array_map;
|
||||
use function is_array;
|
||||
|
||||
/** @deprecated use Doctrine\Persistence\Reflection\EnumReflectionProperty instead */
|
||||
final class ReflectionEnumProperty extends ReflectionProperty
|
||||
{
|
||||
/** @param class-string<BackedEnum> $enumType */
|
||||
public function __construct(
|
||||
private readonly ReflectionProperty $originalReflectionProperty,
|
||||
private readonly string $enumType,
|
||||
) {
|
||||
parent::__construct(
|
||||
$originalReflectionProperty->class,
|
||||
$originalReflectionProperty->name,
|
||||
);
|
||||
}
|
||||
|
||||
public function getValue(object|null $object = null): int|string|array|null
|
||||
{
|
||||
if ($object === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$enum = $this->originalReflectionProperty->getValue($object);
|
||||
|
||||
if ($enum === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_array($enum)) {
|
||||
return array_map(
|
||||
static fn (BackedEnum $item): int|string => $item->value,
|
||||
$enum,
|
||||
);
|
||||
}
|
||||
|
||||
return $enum->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $object
|
||||
* @param int|string|int[]|string[]|BackedEnum|BackedEnum[]|null $value
|
||||
*/
|
||||
public function setValue(mixed $object, mixed $value = null): void
|
||||
{
|
||||
if ($value !== null) {
|
||||
if (is_array($value)) {
|
||||
$value = array_map(fn (int|string|BackedEnum $item): BackedEnum => $this->initializeEnumValue($object, $item), $value);
|
||||
} else {
|
||||
$value = $this->initializeEnumValue($object, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$this->originalReflectionProperty->setValue($object, $value);
|
||||
}
|
||||
|
||||
private function initializeEnumValue(object $object, int|string|BackedEnum $value): BackedEnum
|
||||
{
|
||||
if ($value instanceof BackedEnum) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$enumType = $this->enumType;
|
||||
|
||||
try {
|
||||
return $enumType::from($value);
|
||||
} catch (ValueError $e) {
|
||||
throw MappingException::invalidEnumValue(
|
||||
$object::class,
|
||||
$this->originalReflectionProperty->name,
|
||||
(string) $value,
|
||||
$enumType,
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
backend/vendor/doctrine/orm/src/Mapping/ReflectionReadonlyProperty.php
vendored
Normal file
49
backend/vendor/doctrine/orm/src/Mapping/ReflectionReadonlyProperty.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function assert;
|
||||
use function func_get_args;
|
||||
use function func_num_args;
|
||||
use function is_object;
|
||||
use function sprintf;
|
||||
|
||||
/** @internal */
|
||||
final class ReflectionReadonlyProperty extends ReflectionProperty
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ReflectionProperty $wrappedProperty,
|
||||
) {
|
||||
if (! $wrappedProperty->isReadOnly()) {
|
||||
throw new InvalidArgumentException('Given property is not readonly.');
|
||||
}
|
||||
|
||||
parent::__construct($wrappedProperty->class, $wrappedProperty->name);
|
||||
}
|
||||
|
||||
public function getValue(object|null $object = null): mixed
|
||||
{
|
||||
return $this->wrappedProperty->getValue(...func_get_args());
|
||||
}
|
||||
|
||||
public function setValue(mixed $objectOrValue, mixed $value = null): void
|
||||
{
|
||||
if (func_num_args() < 2 || $objectOrValue === null || ! $this->isInitialized($objectOrValue)) {
|
||||
$this->wrappedProperty->setValue(...func_get_args());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
assert(is_object($objectOrValue));
|
||||
|
||||
if (parent::getValue($objectOrValue) !== $value) {
|
||||
throw new LogicException(sprintf('Attempting to change readonly property %s::$%s.', $this->class, $this->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
18
backend/vendor/doctrine/orm/src/Mapping/SequenceGenerator.php
vendored
Normal file
18
backend/vendor/doctrine/orm/src/Mapping/SequenceGenerator.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PROPERTY)]
|
||||
final class SequenceGenerator implements MappingAttribute
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string|null $sequenceName = null,
|
||||
public readonly int $allocationSize = 1,
|
||||
public readonly int $initialValue = 1,
|
||||
) {
|
||||
}
|
||||
}
|
||||
45
backend/vendor/doctrine/orm/src/Mapping/Table.php
vendored
Normal file
45
backend/vendor/doctrine/orm/src/Mapping/Table.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class Table implements MappingAttribute
|
||||
{
|
||||
/**
|
||||
* @param array<Index>|null $indexes
|
||||
* @param array<UniqueConstraint>|null $uniqueConstraints
|
||||
* @param array<string,mixed> $options
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string|null $name = null,
|
||||
public readonly string|null $schema = null,
|
||||
public readonly array|null $indexes = null,
|
||||
public readonly array|null $uniqueConstraints = null,
|
||||
public readonly array $options = [],
|
||||
) {
|
||||
if ($this->indexes !== null) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/11357',
|
||||
'Providing the property $indexes on %s does not have any effect and will be removed in Doctrine ORM 4.0. Please use the %s attribute instead.',
|
||||
self::class,
|
||||
Index::class,
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->uniqueConstraints !== null) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/orm/pull/11357',
|
||||
'Providing the property $uniqueConstraints on %s does not have any effect and will be removed in Doctrine ORM 4.0. Please use the %s attribute instead.',
|
||||
self::class,
|
||||
UniqueConstraint::class,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user