diff --git a/src/php/ContextFactory.php b/src/php/ContextFactory.php
index bbefa823f21280c1f934d1456f7ff76ee2a19a45..30ef01825c3f88bb1fda3c7575245435d6ea8107 100644
--- a/src/php/ContextFactory.php
+++ b/src/php/ContextFactory.php
@@ -49,7 +49,10 @@ final class ContextFactory implements ContextFactoryInterface
private $reflectionTypeFactory;
/** @var TypeFactoryInterface */
- private $builtinTypeFactory;
+ private $builtinClassesTypeFactory;
+
+ /** @var TypeFactoryInterface */
+ private $builtinScalarsTypeFactory;
/**
* ContextFactory constructor.
@@ -60,7 +63,8 @@ final class ContextFactory implements ContextFactoryInterface
$this->nullableTypeFactory = new NullableTypeFactory();
$this->collectionTypeFactory = new CollectionTypeFactory();
$this->reflectionTypeFactory = TypeCache::decorate(new ReflectionTypeFactory($propertyInfoExtractor));
- $this->builtinTypeFactory = BuiltinTypeFactory::createDefault();
+ $this->builtinClassesTypeFactory = BuiltinTypeFactory::createWithClasses();
+ $this->builtinScalarsTypeFactory = BuiltinTypeFactory::createWithScalars();
}
/**
@@ -74,13 +78,14 @@ final class ContextFactory implements ContextFactoryInterface
new CompositeTypeFactory([
$this->nullableTypeFactory,
$this->collectionTypeFactory,
+ $this->builtinClassesTypeFactory,
DeferrableTypeFactory::decorate(
new CompositeTypeFactory([
$serializationMapper,
$this->reflectionTypeFactory
])
),
- $this->builtinTypeFactory
+ $this->builtinScalarsTypeFactory
])
);
diff --git a/src/php/ModelGenerator.php b/src/php/ModelGenerator.php
index a4c4c05d0b334a74ea3994e89e588562214854c6..31af395056502df38a44a7319894565ba3bc1813 100644
--- a/src/php/ModelGenerator.php
+++ b/src/php/ModelGenerator.php
@@ -193,14 +193,6 @@ final class ModelGenerator
{
$repositories = [];
-// // Premier passage pour prégénérer des références aux ressources
-// foreach ($this->getResourceMetadata() as $class => $resourceMeta) {
-// /* @var ClassName $class */
-// /* @var ResourceMetadata $resourceMeta */
-// $ref = $this->typeFactory->defer($class->getFullName());
-// $this->typeFactory->add($resourceMeta->getBaseName(), $ref);
-// }
-
// Maintenant on génére les repositories
foreach ($this->getResourceMetadata() as $class => $resourceMeta) {
/* @var ClassName $class */
diff --git a/src/php/Models/Types/Factory/BuiltinTypeFactory.php b/src/php/Models/Types/Factory/BuiltinTypeFactory.php
index fa27f52fe20539c09ba3254c4f235de18d998391..20025a2cb97e8ea3f692ee876307a1a968e1ae5f 100644
--- a/src/php/Models/Types/Factory/BuiltinTypeFactory.php
+++ b/src/php/Models/Types/Factory/BuiltinTypeFactory.php
@@ -65,7 +65,7 @@ class BuiltinTypeFactory implements TypeFactoryInterface
*/
public function createType(PropertyType $type, ContextInterface $context): Type
{
- Assertion::true($this->supportsType($type, $context));
+ Assertion::true($this->supportsType($type, $context), '%s is not supported by '. static::class);
return $this->types[TypeHelper::getTypeKey($type)];
}
@@ -73,7 +73,7 @@ class BuiltinTypeFactory implements TypeFactoryInterface
/**
* @return BuiltinTypeFactory
*/
- public static function createDefault(): BuiltinTypeFactory
+ public static function createWithScalars(): BuiltinTypeFactory
{
$types = [
PropertyType::BUILTIN_TYPE_ARRAY => BuiltinType::get('Array'),
@@ -82,13 +82,26 @@ class BuiltinTypeFactory implements TypeFactoryInterface
PropertyType::BUILTIN_TYPE_INT => BuiltinType::get('number'),
PropertyType::BUILTIN_TYPE_NULL => BuiltinType::get('null'),
PropertyType::BUILTIN_TYPE_STRING => BuiltinType::get('string'),
- 'Ramsey\Uuid\UuidInterface' => UUID::get(),
- 'DateTime' => BuiltinType::get('string'),
- 'DateTimeInterface' => BuiltinType::get('string'),
- 'DateTimeImmutable' => BuiltinType::get('string'),
- 'Ordering' => new Alias('Ordering', Union::create([StringConst::get('asc'), StringConst::get('desc')]), 'Allowed values for ordering parameters'),
];
return new BuiltinTypeFactory($types);
}
+
+ /**
+ * @return BuiltinTypeFactory
+ */
+ public static function createWithClasses(): BuiltinTypeFactory
+ {
+ $types = [
+ 'Ramsey\Uuid\Uuid' => UUID::get(),
+ 'Ramsey\Uuid\UuidInterface' => UUID::get(),
+ 'DateTime' => BuiltinType::get('string'),
+ 'DateTimeInterface' => BuiltinType::get('string'),
+ 'DateTimeImmutable' => BuiltinType::get('string'),
+ 'Ordering' => new Alias('Ordering', Union::create([StringConst::get('asc'), StringConst::get('desc')]), 'Allowed values for ordering parameters'),
+ ];
+
+ return new BuiltinTypeFactory($types);
+ }
+
}
diff --git a/src/php/Models/Types/Factory/CollectionTypeFactory.php b/src/php/Models/Types/Factory/CollectionTypeFactory.php
index efac62781466b8a22bff16f5c8b031ba58ffe439..84bfc3208ad99a418287b7b782d4a6b16c60ba7c 100644
--- a/src/php/Models/Types/Factory/CollectionTypeFactory.php
+++ b/src/php/Models/Types/Factory/CollectionTypeFactory.php
@@ -46,7 +46,7 @@ final class CollectionTypeFactory implements TypeFactoryInterface
*/
public function createType(PropertyType $type, ContextInterface $context): Type
{
- Assertion::true($this->supportsType($type, $context));
+ Assertion::true($this->supportsType($type, $context), '%s is not supported by ' . static::class);
$valueType = $type->getCollectionValueType();
if (!$valueType) {
diff --git a/src/php/Models/Types/Factory/NullableTypeFactory.php b/src/php/Models/Types/Factory/NullableTypeFactory.php
index 7b986abba973b92c05789c764ea14bd4f3f576dc..11e71ff818a1aef9103f387e9ba2ee41c44efe17 100644
--- a/src/php/Models/Types/Factory/NullableTypeFactory.php
+++ b/src/php/Models/Types/Factory/NullableTypeFactory.php
@@ -45,7 +45,7 @@ final class NullableTypeFactory implements TypeFactoryInterface
*/
public function createType(PropertyType $type, ContextInterface $context): Type
{
- Assertion::true($this->supportsType($type, $context));
+ Assertion::true($this->supportsType($type, $context), '%s is not supported by ' . static::class);
return Union::create([BuiltinType::get('null'), $context->createType(TypeHelper::notNullable($type))]);
}
diff --git a/src/php/Models/Types/Factory/ReflectionTypeFactory.php b/src/php/Models/Types/Factory/ReflectionTypeFactory.php
index 76d75e0aed5f2082b7f13e9adf274a5d61898231..00788752b1bebf79cf241a5c010685640c9a7de7 100644
--- a/src/php/Models/Types/Factory/ReflectionTypeFactory.php
+++ b/src/php/Models/Types/Factory/ReflectionTypeFactory.php
@@ -62,7 +62,7 @@ final class ReflectionTypeFactory implements TypeFactoryInterface
*/
public function createType(PropertyType $type, ContextInterface $context): Type
{
- Assertion::true($this->supportsType($type, $context));
+ Assertion::true($this->supportsType($type, $context), '%s is not supported by ' . static::class);
$fqcn = $type->getClassName();
$propertyNames = $this->propertyInfoExtractor->getProperties($fqcn);
diff --git a/src/php/Models/Types/Factory/TypeCache.php b/src/php/Models/Types/Factory/TypeCache.php
index e6db8591b377fe30a5ddb393db909cf7dd35f679..1f0a53db94b6e530ef2edc443776d30ba249210d 100644
--- a/src/php/Models/Types/Factory/TypeCache.php
+++ b/src/php/Models/Types/Factory/TypeCache.php
@@ -59,7 +59,7 @@ final class TypeCache extends AbstractTypeFactoryDecorator
*/
public function createType(PropertyType $type, ContextInterface $context): Type
{
- Assertion::true($this->supportsType($type, $context));
+ Assertion::true($this->supportsType($type, $context), $type->getClassName() . ' is not supported by ' . static::class);
$key = TypeHelper::getTypeKey($type);
diff --git a/src/php/SerializationMapper.php b/src/php/SerializationMapper.php
index 75989664e278088ba7873c4d5ac99a7b6412845c..2bfa3f149ec4f5572263678233cb436921f421a0 100644
--- a/src/php/SerializationMapper.php
+++ b/src/php/SerializationMapper.php
@@ -180,28 +180,14 @@ final class SerializationMapper implements TypeFactoryInterface
private function mapProperties(ClassInfo $classInfo, ContextInterface $context): array
{
$properties = [];
- $identifierCount = 0;
foreach ($classInfo->getConcreteProperties() as $propertyMeta) {
/** @var PropertyMetadata $propertyMeta */
- if ($propertyMeta->isIdentifier()) {
- ++$identifierCount;
- }
$property = $this->mapProperty($propertyMeta, $context);
$properties[$property->getName()] = $property;
}
- if ($identifierCount > 1) {
- throw new DomainException(
- sprintf(
- 'Resource %s must have at most one identifier, found %d',
- $classInfo->getBaseName(),
- $identifierCount
- )
- );
- }
-
if ($this->withAtFields && $classInfo->isResource()) {
$properties['@id'] = new Property(
'@id',
diff --git a/tests/Fixtures/Entity/EntityTrait.php b/tests/Fixtures/Entity/EntityTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..c017e0adec3b10a3854ed293ca527a72135fdc89
--- /dev/null
+++ b/tests/Fixtures/Entity/EntityTrait.php
@@ -0,0 +1,49 @@
+<?php declare(strict_types=1);
+/**
+ * Copyright (C) 2019 IRSTEA
+ * All rights reserved.
+ *
+ * @copyright 2019 IRSTEA
+ * @author guillaume.perreal
+ */
+
+
+namespace Irstea\NgModelGeneratorBundle\Tests\Fixtures\Entity;
+
+
+use Doctrine\ORM\Mapping as ORM;
+use Ramsey\Uuid\Uuid;
+
+/**
+ * Class EntityTrait
+ */
+trait EntityTrait
+{
+ /**
+ * N.B. : il est nécessaire d'utiliser le FQCN ici sinon le lecteur d'annotation bug
+ * et ne retrouve pas le bon namespace.
+ *
+ * @var \Ramsey\Uuid\UuidInterface
+ * @ORM\Id()
+ * @ORM\Column(type="uuid", unique=true)
+ */
+ private $id;
+
+ /**
+ * @throws \Exception
+ */
+ private function createId()
+ {
+ $this->id = Uuid::uuid4();
+ }
+
+ /**
+ * Get id.
+ *
+ * @return \Ramsey\Uuid\UuidInterface
+ */
+ public function getId(): \Ramsey\Uuid\UuidInterface
+ {
+ return $this->id;
+ }
+}
diff --git a/tests/Fixtures/Entity/Person.php b/tests/Fixtures/Entity/Person.php
index 3bc68a7e77df4c6d372d0a46e223079476fd0417..55b876e7899806e0c9e12ba59c3712fd4c675ba6 100644
--- a/tests/Fixtures/Entity/Person.php
+++ b/tests/Fixtures/Entity/Person.php
@@ -15,8 +15,6 @@ use ApiPlatform\Core\Annotation as API;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
-use Ramsey\Uuid\Uuid;
-use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
@@ -27,25 +25,8 @@ use Symfony\Component\Validator\Constraints as Assert;
*/
final class Person
{
- /**
- * @var UuidInterface
- * @ORM\Id()
- * @ORM\Column(type="uuid")
- */
- private $id;
-
- /**
- * @var \DateTimeInterface
- * @ORM\Column(type="datetimetz_immutable")
- * @Assert\NotNull()
- */
- private $createdAt;
-
- /**
- * @var \DateTimeInterface|null
- * @ORM\Column(type="datetimetz_immutable", nullable=true)
- */
- private $updatedAt;
+ use EntityTrait;
+ use TimestampedTrait;
/**
* @var string
@@ -85,17 +66,26 @@ final class Person
*/
private $participeTo;
+ /**
+ * @var Structure|null
+ * @ORM\ManyToOne(targetEntity=Structure::class)
+ */
+ private $affectation;
+
/**
* Person constructor.
* @param string $firstName
* @param string $lastName
* @param string|null $email
* @param string|null $phoneNumber
+ * @param Structure|null $affectation
+ * @throws \Exception
*/
- public function __construct(string $firstName, string $lastName, string $email = null, string $phoneNumber = null)
+ public function __construct(string $firstName, string $lastName, string $email = null, string $phoneNumber = null, Structure $affectation = null)
{
- $this->id = Uuid::uuid4();
- $this->createdAt = new \DateTimeImmutable();
+ $this->createId();
+ $this->created();
+
$this->firstName = $firstName;
$this->lastName = $lastName;
$this->email = $email;
@@ -103,36 +93,7 @@ final class Person
$this->managedProjects = new ArrayCollection();
$this->participeTo = new ArrayCollection();
- }
-
- /**
- * Get id.
- *
- * @return UuidInterface
- */
- public function getId(): UuidInterface
- {
- return $this->id;
- }
-
- /**
- * Get createdAt.
- *
- * @return \DateTimeInterface
- */
- public function getCreatedAt(): \DateTimeInterface
- {
- return $this->createdAt;
- }
-
- /**
- * Get updatedAt.
- *
- * @return \DateTimeInterface|null
- */
- public function getUpdatedAt(): ?\DateTimeInterface
- {
- return $this->updatedAt;
+ $this->affectation = $affectation;
}
/**
@@ -175,6 +136,16 @@ final class Person
return $this->phoneNumber;
}
+ /**
+ * Get affectation.
+ *
+ * @return Structure|null
+ */
+ public function getAffectation(): ?Structure
+ {
+ return $this->affectation;
+ }
+
/**
* Set firstName.
*
@@ -183,7 +154,7 @@ final class Person
public function setFirstName(string $firstName): void
{
$this->firstName = $firstName;
- $this->updatedAt = new \DateTimeImmutable();
+ $this->updated();
}
/**
@@ -194,7 +165,7 @@ final class Person
public function setLastName(string $lastName): void
{
$this->lastName = $lastName;
- $this->updatedAt = new \DateTimeImmutable();
+ $this->updated();
}
/**
@@ -205,7 +176,7 @@ final class Person
public function setEmail(?string $email): void
{
$this->email = $email;
- $this->updatedAt = new \DateTimeImmutable();
+ $this->updated();
}
/**
@@ -216,7 +187,18 @@ final class Person
public function setPhoneNumber(?string $phoneNumber): void
{
$this->phoneNumber = $phoneNumber;
- $this->updatedAt = new \DateTimeImmutable();
+ $this->updated();
+ }
+
+ /**
+ * Set affectation.
+ *
+ * @param Structure|null $affectation
+ */
+ public function setAffectation(?Structure $affectation): void
+ {
+ $this->affectation = $affectation;
+ $this->updated();
}
/**
diff --git a/tests/Fixtures/Entity/Project.php b/tests/Fixtures/Entity/Project.php
index bf3da48645b5c737714e0609b1937891ed5eb491..e56993fa97b171e789af2dfc5e184e5159a39b0e 100644
--- a/tests/Fixtures/Entity/Project.php
+++ b/tests/Fixtures/Entity/Project.php
@@ -16,7 +16,6 @@ use Assert\Assertion;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
-use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Validator\Constraints as Assert;
@@ -28,12 +27,8 @@ use Symfony\Component\Validator\Constraints as Assert;
*/
final class Project
{
- /**
- * @var UuidInterface
- * @ORM\Id()
- * @ORM\Column(type="uuid")
- */
- private $id;
+ use EntityTrait;
+ use TimestampedTrait;
/**
* @ORM\Column()
@@ -78,7 +73,9 @@ final class Project
*/
public function __construct(string $name, ?string $acronym, \DateTimeImmutable $startDate, Person $manager, array $participants)
{
- $this->id = Uuid::uuid4();
+ $this->createId();
+ $this->created();
+
$this->name = $name;
$this->acronym = $acronym;
$this->startDate = $startDate;
@@ -116,6 +113,7 @@ final class Project
public function setName(string $name): void
{
$this->name = $name;
+ $this->updated();
}
/**
@@ -136,6 +134,7 @@ final class Project
public function setAcronym(?string $acronym): void
{
$this->acronym = $acronym;
+ $this->updated();
}
/**
@@ -156,6 +155,7 @@ final class Project
public function setStartDate(\DateTimeImmutable $startDate): void
{
$this->startDate = $startDate;
+ $this->updated();
}
/**
@@ -176,6 +176,7 @@ final class Project
public function setManager(Person $manager): void
{
$this->manager = $manager;
+ $this->updated();
}
/**
@@ -197,6 +198,7 @@ final class Project
{
if (!$this->participants->contains($person)) {
$this->participants->add($person);
+ $this->updated();
}
}
@@ -207,7 +209,9 @@ final class Project
*/
public function removeParticipant(Person $person): void
{
- $this->participants->removeElement($person);
+ if ($this->participants->contains($person)) {
+ $this->participants->removeElement($person);
+ $this->updated();
+ }
}
-
}
diff --git a/tests/Fixtures/Entity/Structure.php b/tests/Fixtures/Entity/Structure.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3653511d22359820073035a7e749b9166b691de
--- /dev/null
+++ b/tests/Fixtures/Entity/Structure.php
@@ -0,0 +1,114 @@
+<?php declare(strict_types=1);
+/**
+ * Copyright (C) 2019 IRSTEA
+ * All rights reserved.
+ *
+ * @copyright 2019 IRSTEA
+ * @author guillaume.perreal
+ */
+
+
+namespace Irstea\NgModelGeneratorBundle\Tests\Fixtures\Entity;
+
+
+use ApiPlatform\Core\Annotation as API;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Class Structure
+ *
+ * @ORM\Entity()
+ * @API\ApiResource()
+ */
+class Structure
+{
+ use EntityTrait;
+ use TimestampedTrait;
+
+ /**
+ * @ORM\Column()
+ * @var string
+ */
+ private $name;
+
+ /**
+ * @var Structure|null
+ * @ORM\ManyToOne(targetEntity=Structure::class, inversedBy="children")
+ */
+ private $parent;
+
+ /**
+ * @var Structure[]|Collection
+ * @ORM\OneToMany(targetEntity=Structure::class, mappedBy="parent")
+ */
+ private $children;
+
+ /**
+ * Structure constructor.
+ * @param string $name
+ * @param Structure|null $parent
+ */
+ public function __construct(string $name, self $parent = null)
+ {
+ $this->createId();
+ $this->created();
+
+ $this->name = $name;
+ $this->parent = $parent;
+ $this->children = New ArrayCollection();
+ }
+
+ /**
+ * Get name.
+ *
+ * @return string
+ */
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+ /**
+ * Get parent.
+ *
+ * @return Structure|null
+ */
+ public function getParent(): ?Structure
+ {
+ return $this->parent;
+ }
+
+ /**
+ * Set name.
+ *
+ * @param string $name
+ */
+ public function setName(string $name): void
+ {
+ $this->name = $name;
+ $this->updated();
+ }
+
+ /**
+ * Set parent.
+ *
+ * @param Structure|null $parent
+ */
+ public function setParent(?Structure $parent): void
+ {
+ $this->parent = $parent;
+ $this->updated();
+ }
+
+ /**
+ * Get children.
+ *
+ * @return Structure[]
+ */
+ public function getChildren(): array
+ {
+ return $this->children->toArray();
+ }
+}
diff --git a/tests/Fixtures/Entity/TimestampedTrait.php b/tests/Fixtures/Entity/TimestampedTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ab137167297df26b94cff002bbfbc441fd61c76
--- /dev/null
+++ b/tests/Fixtures/Entity/TimestampedTrait.php
@@ -0,0 +1,61 @@
+<?php declare(strict_types=1);
+/**
+ * Copyright (C) 2019 IRSTEA
+ * All rights reserved.
+ *
+ * @copyright 2019 IRSTEA
+ * @author guillaume.perreal
+ */
+
+
+namespace Irstea\NgModelGeneratorBundle\Tests\Fixtures\Entity;
+
+
+/**
+ * Trait TimestampedTrait
+ */
+trait TimestampedTrait
+{
+ /**
+ * @var \DateTimeInterface
+ * @ORM\Column(type="datetimetz_immutable")
+ */
+ private $createdAt;
+
+ /**
+ * @var \DateTimeInterface|null
+ * @ORM\Column(type="datetimetz_immutable", nullable=true)
+ */
+ private $updatedAt;
+
+ protected function created(): void
+ {
+ $this->createdAt = new \DateTimeImmutable();
+ }
+
+ protected function updated(): void
+ {
+ $this->updatedAt = new \DateTimeImmutable();
+ }
+
+ /**
+ * Get createdAt.
+ *
+ * @return \DateTimeInterface
+ */
+ public function getCreatedAt(): \DateTimeInterface
+ {
+ return $this->createdAt;
+ }
+
+ /**
+ * Get updatedAt.
+ *
+ * @return \DateTimeInterface|null
+ */
+ public function getUpdatedAt(): ?\DateTimeInterface
+ {
+ return $this->updatedAt;
+ }
+
+}