Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions config/makers.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@
use Zenstruck\Foundry\Maker\Factory\FactoryCandidatesClassesExtractor;
use Zenstruck\Foundry\Maker\Factory\FactoryClassMap;
use Zenstruck\Foundry\Maker\Factory\FactoryGenerator;
use Zenstruck\Foundry\Maker\Factory\LegacyORMDefaultPropertiesGuesser;
use Zenstruck\Foundry\Maker\Factory\NoPersistenceObjectsAutoCompleter;
use Zenstruck\Foundry\Maker\Factory\ObjectDefaultPropertiesGuesser;
use Zenstruck\Foundry\Maker\Factory\ODMDefaultPropertiesGuesser;
use Zenstruck\Foundry\Maker\Factory\ORMDefaultPropertiesGuesser;
use Zenstruck\Foundry\Maker\MakeFactory;
use Zenstruck\Foundry\Maker\MakeStory;
use Zenstruck\Foundry\Maker\NamespaceGuesser;
use Zenstruck\Foundry\ORM\DoctrineOrmVersionGuesser;

return static function(ContainerConfigurator $container): void {
$container->services()
Expand All @@ -42,7 +40,7 @@
])
->tag('maker.command')

->set('.zenstruck_foundry.maker.factory.orm_default_properties_guesser', DoctrineOrmVersionGuesser::isOrmV3() ? ORMDefaultPropertiesGuesser::class : LegacyORMDefaultPropertiesGuesser::class)
->set('.zenstruck_foundry.maker.factory.orm_default_properties_guesser', ORMDefaultPropertiesGuesser::class)
->args([
service('.zenstruck_foundry.persistence_manager')->nullOnInvalid(),
service('.zenstruck_foundry.maker.factory.factory_class_map'),
Expand Down
6 changes: 2 additions & 4 deletions config/orm.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver;
use Zenstruck\Foundry\ORM\DoctrineOrmVersionGuesser;
use Zenstruck\Foundry\ORM\OrmV2PersistenceStrategy;
use Zenstruck\Foundry\ORM\OrmV3PersistenceStrategy;
use Zenstruck\Foundry\ORM\ORMPersistenceStrategy;
use Zenstruck\Foundry\ORM\ResetDatabase\BaseOrmResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\DamaDatabaseResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\OrmResetter;

return static function(ContainerConfigurator $container): void {
$container->services()
->set('.zenstruck_foundry.persistence_strategy.orm', DoctrineOrmVersionGuesser::isOrmV3() ? OrmV3PersistenceStrategy::class : OrmV2PersistenceStrategy::class)
->set('.zenstruck_foundry.persistence_strategy.orm', ORMPersistenceStrategy::class)
->args([
service('doctrine'),
])
Expand Down
4 changes: 1 addition & 3 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,5 @@ parameters:
- tests/Fixture/Maker/expected/can_create_factory_with_embeddable_odm.php
- tests/Fixture/Maker/expected/can_create_factory_with_embeddable_orm.php

# phpstan runs with orm 3 - there are too many failures in these files which are compatible with orm 2
- ./src/Maker/Factory/LegacyORMDefaultPropertiesGuesser.php
# dual ORM/ODM FieldMapping type in this file requires exclusion
- ./src/Maker/Factory/DoctrineScalarFieldsDefaultPropertiesGuesser.php
- ./src/ORM/OrmV2PersistenceStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ public function supports(MakeFactoryData $makeFactoryData): bool
return $makeFactoryData->isPersisted();
}

// handles both ORM 3 & 4
private function extractFieldMappingData(FieldMapping|array $fieldMapping, string $field, mixed $default = null): mixed
{
if ($fieldMapping instanceof FieldMapping) {
Expand Down
83 changes: 0 additions & 83 deletions src/Maker/Factory/LegacyORMDefaultPropertiesGuesser.php

This file was deleted.

5 changes: 0 additions & 5 deletions src/Maker/Factory/ORMDefaultPropertiesGuesser.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use Doctrine\ORM\Mapping\ClassMetadata as ORMClassMetadata;
use Doctrine\ORM\Mapping\ToOneAssociationMapping;
use Symfony\Component\Console\Style\SymfonyStyle;
use Zenstruck\Foundry\ORM\DoctrineOrmVersionGuesser;
use Zenstruck\Foundry\Persistence\Exception\NoPersistenceStrategy;

/**
Expand All @@ -24,10 +23,6 @@ final class ORMDefaultPropertiesGuesser extends AbstractDoctrineDefaultPropertie
{
public function __invoke(SymfonyStyle $io, MakeFactoryData $makeFactoryData, MakeFactoryQuery $makeFactoryQuery): void
{
if (!DoctrineOrmVersionGuesser::isOrmV3()) {
return;
}

$metadata = $this->getClassMetadata($makeFactoryData);

if (!$metadata instanceof ORMClassMetadata) {
Expand Down
22 changes: 0 additions & 22 deletions src/ORM/DoctrineOrmVersionGuesser.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@
namespace Zenstruck\Foundry\ORM;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\AssociationMapping;
use Doctrine\ORM\Mapping\ManyToOneAssociationMapping;
use Doctrine\ORM\Mapping\MappingException as ORMMappingException;
use Doctrine\ORM\Mapping\OneToManyAssociationMapping;
use Doctrine\ORM\Mapping\OneToOneAssociationMapping;
use Doctrine\Persistence\Mapping\MappingException;
use Zenstruck\Foundry\Persistence\PersistenceStrategy;
use Zenstruck\Foundry\Persistence\Relationship\ManyToOneRelationship;
use Zenstruck\Foundry\Persistence\Relationship\OneToManyRelationship;
use Zenstruck\Foundry\Persistence\Relationship\OneToOneRelationship;
use Zenstruck\Foundry\Persistence\Relationship\RelationshipMetadata;

/**
* @author Kevin Bond <kevinbond@gmail.com>
Expand All @@ -24,16 +32,16 @@
* @method EntityManagerInterface objectManagerFor(string $class)
* @method list<EntityManagerInterface> objectManagers()
*/
abstract class AbstractORMPersistenceStrategy extends PersistenceStrategy
final class ORMPersistenceStrategy extends PersistenceStrategy
{
final public function contains(object $object): bool
public function contains(object $object): bool
{
$em = $this->objectManagerFor($object::class);

return $em->contains($object) && !$em->getUnitOfWork()->isScheduledForInsert($object);
}

final public function hasChanges(object $object): bool
public function hasChanges(object $object): bool
{
$em = $this->objectManagerFor($object::class);

Expand All @@ -50,12 +58,12 @@ final public function hasChanges(object $object): bool
return (bool) $unitOfWork->getEntityChangeSet($object);
}

final public function truncate(string $class): void
public function truncate(string $class): void
{
$this->objectManagerFor($class)->createQuery("DELETE {$class} e")->execute();
}

final public function embeddablePropertiesFor(object $object, string $owner): ?array
public function embeddablePropertiesFor(object $object, string $owner): ?array
{
try {
$metadata = $this->objectManagerFor($owner)->getClassMetadata($object::class);
Expand All @@ -76,17 +84,17 @@ final public function embeddablePropertiesFor(object $object, string $owner): ?a
return $properties;
}

final public function isEmbeddable(object $object): bool
public function isEmbeddable(object $object): bool
{
return $this->objectManagerFor($object::class)->getClassMetadata($object::class)->isEmbeddedClass;
}

final public function isScheduledForInsert(object $object): bool
public function isScheduledForInsert(object $object): bool
{
return $this->objectManagerFor($object::class)->getUnitOfWork()->isScheduledForInsert($object);
}

final public function managedNamespaces(): array
public function managedNamespaces(): array
{
$namespaces = [];

Expand All @@ -97,7 +105,7 @@ final public function managedNamespaces(): array
return \array_values(\array_merge(...$namespaces));
}

final public function getIdentifierValues(object $object): array
public function getIdentifierValues(object $object): array
{
$identifiers = $this->classMetadata($object::class)->getIdentifierValues($object);

Expand All @@ -118,4 +126,60 @@ function(mixed $value) use ($object) {
$identifiers
);
}

public function bidirectionalRelationshipMetadata(string $parent, string $child, string $field): ?RelationshipMetadata
{
$associationMapping = $this->getAssociationMapping($parent, $child, $field);

if (null === $associationMapping) {
return null;
}

if (!\is_a(
$child,
$associationMapping->targetEntity,
allow_string: true
)) { // is_a() handles inheritance as well
throw new \LogicException("Cannot find correct association named \"{$field}\" between classes [parent: \"{$parent}\", child: \"{$child}\"]");
}

$inverseField = $associationMapping->isOwningSide() ? $associationMapping->inversedBy : $associationMapping->mappedBy;

if (null === $inverseField) {
return null;
}

return match (true) {
$associationMapping instanceof OneToManyAssociationMapping => new OneToManyRelationship(
inverseField: $inverseField,
collectionIndexedBy: $associationMapping->isIndexed() ? $associationMapping->indexBy() : null
),
$associationMapping instanceof OneToOneAssociationMapping => new OneToOneRelationship(
inverseField: $inverseField,
isOwning: $associationMapping->isOwningSide()
),
$associationMapping instanceof ManyToOneAssociationMapping => new ManyToOneRelationship(
inverseField: $inverseField,
),
default => null,
};
}

/**
* @param class-string $entityClass
*/
private function getAssociationMapping(string $entityClass, string $targetEntity, string $field): ?AssociationMapping
{
try {
$associationMapping = $this->objectManagerFor($entityClass)->getClassMetadata($entityClass)->getAssociationMapping($field);
} catch (MappingException|ORMMappingException) {
return null;
}

if (!\is_a($targetEntity, $associationMapping->targetEntity, allow_string: true)) {
return null;
}

return $associationMapping;
}
}
Loading
Loading