From 91e4d585ff01d72fdeb4ec4809c19b31a2d5ab9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 12 May 2021 17:51:37 +0200 Subject: [PATCH] add a discrimnator type on onbjects --- docs/source/development/api.rst | 53 ++++++++++++++++++- src/Bundle/ChillMainBundle/Entity/User.php | 4 ++ .../DoctrineExistingEntityNormalizer.php | 47 +++++++++++++--- .../Serializer/Normalizer/UserNormalizer.php | 6 ++- .../DoctrineExistingEntityNormalizerTest.php | 51 ++++++++++++++++++ .../AccompanyingCourseApiController.php | 8 +-- .../Entity/AccompanyingPeriod.php | 13 +++-- .../AccompanyingPeriodParticipation.php | 9 ++++ .../ChillPersonBundle/Entity/Person.php | 4 ++ ...ompanyingPeriodParticipationNormalizer.php | 1 + .../Normalizer/PersonNormalizer.php | 35 ++---------- .../AccompanyingCourseApiControllerTest.php | 48 +++++++++++++---- .../ChillPersonBundle/chill.api.specs.yaml | 3 ++ .../ChillPersonBundle/config/services.yaml | 6 ++- .../config/services/serializer.yaml | 11 +--- .../Entity/ThirdParty.php | 5 +- .../Normalizer/ThirdPartyNormalizer.php | 41 +------------- 17 files changed, 236 insertions(+), 109 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php diff --git a/docs/source/development/api.rst b/docs/source/development/api.rst index d6f63eea3..feb4fd86a 100644 --- a/docs/source/development/api.rst +++ b/docs/source/development/api.rst @@ -49,7 +49,12 @@ Ensure that those lines are present in your file `app/config/routing.yml`: Create your model ***************** -Create your model on the usual way: +Create your model on the usual way. + +If you do not use a `custom normalizer `_, you must add `annotations to create serialization groups `_. Those groups are, by defaults: + +* :code:`read` for GET requests; +* :code:`write` for POST, PUT and PATCH requests .. code-block:: php @@ -57,6 +62,7 @@ Create your model on the usual way: use Chill\PersonBundle\Entity\AccompanyingPeriod\OriginRepository; use Doctrine\ORM\Mapping as ORM; + use Symfony\Component\Serializer\Annotation\Groups; /** * @ORM\Entity(repositoryClass=OriginRepository::class) @@ -68,16 +74,19 @@ Create your model on the usual way: * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") + * @Groups({"read"}) */ private $id; /** * @ORM\Column(type="json") + * @Groups({"read", "write"}) */ private $label; /** * @ORM\Column(type="date_immutable", nullable=true) + * @Groups({"read", "write"}) */ private $noActiveAfter; @@ -215,6 +224,48 @@ You can also define a role for each method. In this case, this role is used for GET: MY_ROLE_SEE HEAD: MY ROLE_SEE +Edit an entity: PUT and PATCH requests +======================================= + +By default, PUT and PATCH requests are not enabled. You may enable it into the configuration: + + +.. code-block:: yaml + + # config/packages/chill_main.yaml + chill_main: + apis: + accompanying_period_origin: + base_path: '/api/1.0/person/bla/bla' + class: 'Chill\PersonBundle\Entity\Blah' + name: bla + actions: + _entity: + methods: + GET: true + HEAD: true + PUT: true + PATCH: true + roles: + GET: MY_ROLE_SEE + HEAD: MY ROLE_SEE + HEAD: MY ROLE_UPDATE + HEAD: MY ROLE_UPDATE + +.. note:: + + PUT and PATCH requests are handled on a similar way. You may use both without difference, although updating a whole object should use a PUT request, and updating part of the object should use a PATCH request. + +Those two requests allow natively to update all attributes which are present in :code:`write` group, and relation which are connected in ManyToOne relation (the entity under :code:`class` config must be associated with one entity). + +The api will be able to load the associated entity with a simple given :code:`id` and :code:`type`, if + +* if the class is an entity, managed by Doctrine; +* if a discriminator map is present; +* if the given data has two keys: the "discriminator map" (:code:`type`) and the id. Example: :code:`{ "type": "person", "id": 2205 }`; +* if the :code:`setter` is type-hinted. + + Customize the controller ======================== diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 1a46b30a5..11d168f84 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -7,6 +7,7 @@ use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\Security\Core\User\AdvancedUserInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; +use Symfony\Component\Serializer\Annotation\DiscriminatorMap; /** * User @@ -14,6 +15,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; * @ORM\Entity(repositoryClass="Chill\MainBundle\Repository\UserRepository") * @ORM\Table(name="users") * @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region") + * @DiscriminatorMap(typeProperty="type", mapping={ + * "user"=User::class + * }) */ class User implements AdvancedUserInterface { diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php index d8c53ae56..cb2635802 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DoctrineExistingEntityNormalizer.php @@ -6,15 +6,21 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Doctrine\ORM\Mapping\ClassMetadata; +use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; +use Symfony\Component\Serializer\Mapping\ClassMetadataInterface as SerializerMetadata; class DoctrineExistingEntityNormalizer implements DenormalizerInterface { private EntityManagerInterface $em; - public function __construct(EntityManagerInterface $em) + private ClassMetadataFactoryInterface $serializerMetadataFactory; + + + public function __construct(EntityManagerInterface $em, ClassMetadataFactoryInterface $serializerMetadataFactory) { $this->em = $em; + $this->serializerMetadataFactory = $serializerMetadataFactory; } public function denormalize($data, string $type, string $format = null, array $context = []) @@ -29,10 +35,37 @@ class DoctrineExistingEntityNormalizer implements DenormalizerInterface public function supportsDenormalization($data, string $type, string $format = null) { - return \is_array($data) - && count($data) === 1 - && \array_key_exists('id', $data) - && $this->em->getClassMetadata($type) instanceof ClassMetadata; + if (FALSE === \is_array($data)) { + return false; + } + + if (FALSE === \array_key_exists('id', $data)) { + return false; + } + + if (FALSE === $this->em->getClassMetadata($type) instanceof ClassMetadata) { + return false; + } + + // does have serializer metadata, and class discriminator ? + if ($this->serializerMetadataFactory->hasMetadataFor($type)) { + + $classDiscriminator = $this->serializerMetadataFactory + ->getMetadataFor($type)->getClassDiscriminatorMapping(); + + if ($classDiscriminator) { + $typeProperty = $classDiscriminator->getTypeProperty(); + + // check that only 2 keys + // that the second key is property + // and that the type match the class for given type property + return count($data) === 2 + && \array_key_exists($typeProperty, $data) + && $type === $classDiscriminator->getClassForType($data[$typeProperty]); + } + } + + // we do not have any class discriminator. Check that the id is the only one key + return count($data) === 1; } - -} +} diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php index 2a71de52b..4c1dc1523 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/UserNormalizer.php @@ -24,7 +24,7 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface; /** * - * + * @internal we keep this normalizer, because the property 'text' may be replace by a rendering in the future */ class UserNormalizer implements NormalizerInterface { @@ -32,8 +32,10 @@ class UserNormalizer implements NormalizerInterface { /** @var User $user */ return [ + 'type' => 'user', 'id' => $user->getId(), - 'username' => $user->getUsername() + 'username' => $user->getUsername(), + 'text' => $user->getUsername() ]; } diff --git a/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php new file mode 100644 index 000000000..c4f4bc13d --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Serializer/Normalizer/DoctrineExistingEntityNormalizerTest.php @@ -0,0 +1,51 @@ +get(EntityManagerInterface::class); + $serializerFactory = self::$container->get(ClassMetadataFactoryInterface::class); + + $this->normalizer = new DoctrineExistingEntityNormalizer($em, $serializerFactory); + } + + /** + * @dataProvider dataProviderUserId + */ + public function testGetMappedClass($userId) + { + $data = [ 'type' => 'user', 'id' => $userId]; + $supports = $this->normalizer->supportsDenormalization($data, User::class); + + $this->assertTrue($supports); + } + + public function dataProviderUserId() + { + self::bootKernel(); + + $userIds = self::$container->get(EntityManagerInterface::class) + ->getRepository(User::class) + ->createQueryBuilder('u') + ->select('u.id') + ->setMaxResults(1) + ->getQuery() + ->getResult() + ; + + yield [ $userIds[0]['id'] ]; + } +} diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php index 87c9a70df..e9c31fd5d 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php @@ -58,12 +58,12 @@ class AccompanyingCourseApiController extends ApiController if ($errors->count() > 0) { // only format accepted - return $this->json($errors); + return $this->json($errors, 422); } $this->getDoctrine()->getManager()->flush(); - return $this->json($participation); + return $this->json($participation, 200, [], ['groups' => [ 'read' ]]); } public function requestorApi($id, Request $request, string $_format): Response @@ -102,12 +102,12 @@ class AccompanyingCourseApiController extends ApiController if ($errors->count() > 0) { // only format accepted - return $this->json($errors); + return $this->json($errors, 422); } $this->getDoctrine()->getManager()->flush(); - return $this->json($accompanyingPeriod->getRequestor()); + return $this->json($accompanyingPeriod->getRequestor(), 200, [], ['groups' => [ 'read']]); } protected function onPostCheckACL(string $action, Request $request, string $_format, $entity): ?Response diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 2ff24cfb7..6882210e4 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -34,12 +34,16 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Chill\MainBundle\Entity\User; use Symfony\Component\Serializer\Annotation\Groups; +use Symfony\Component\Serializer\Annotation\DiscriminatorMap; /** * AccompanyingPeriod Class * * @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriodRepository") * @ORM\Table(name="chill_person_accompanying_period") + * @DiscriminatorMap(typeProperty="type", mapping={ + * "accompanying_period"=AccompanyingPeriod::class + * }) */ class AccompanyingPeriod { @@ -156,6 +160,7 @@ class AccompanyingPeriod /** * @var string * @ORM\Column(type="string", length=32, nullable=true) + * @Groups({"read"}) */ private $step = self::STEP_DRAFT; @@ -532,7 +537,7 @@ class AccompanyingPeriod return $this->requestorPerson; } - public function setRequestorPerson(Person $requestorPerson = null): self + private function setRequestorPerson(Person $requestorPerson = null): self { $this->requestorPerson = $requestorPerson; @@ -544,7 +549,7 @@ class AccompanyingPeriod return $this->requestorThirdParty; } - public function setRequestorThirdParty(ThirdParty $requestorThirdParty = null): self + private function setRequestorThirdParty(ThirdParty $requestorThirdParty = null): self { $this->requestorThirdParty = $requestorThirdParty; @@ -567,10 +572,10 @@ class AccompanyingPeriod * The requestor is either an instance of ThirdParty, or an * instance of Person * - * @param $requestor Person|ThirdParty + * param $requestor Person|ThirdParty * @return self * @throw UnexpectedValueException if the requestor is not a Person or ThirdParty - * + * @Groups({"write"}) */ public function setRequestor($requestor): self { diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php index c22e84e42..be3a86e6f 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriodParticipation.php @@ -26,6 +26,8 @@ use Chill\PersonBundle\Repository\AccompanyingPeriodParticipationRepository; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\Groups; +use Symfony\Component\Serializer\Annotation\DiscriminatorMap; /** * AccompanyingPeriodParticipation Class @@ -33,6 +35,9 @@ use Doctrine\ORM\Mapping as ORM; * @package Chill\PersonBundle\Entity * @ORM\Entity(repositoryClass=AccompanyingPeriodParticipationRepository::class) * @ORM\Table(name="chill_person_accompanying_period_participation") + * @DiscriminatorMap(typeProperty="type", mapping={ + * "accompanying_period_participation"=AccompanyingPeriodParticipation::class + * }) */ class AccompanyingPeriodParticipation { @@ -40,12 +45,14 @@ class AccompanyingPeriodParticipation * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") + * @Groups({"read"}) */ private $id; /** * @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodParticipations") * @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false) + * @Groups({"read"}) */ private $person; @@ -57,11 +64,13 @@ class AccompanyingPeriodParticipation /** * @ORM\Column(type="date", nullable=false) + * @Groups({"read"}) */ private $startDate; /** * @ORM\Column(type="date", nullable=true) + * @Groups({"read"}) */ private $endDate = null; diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index 3624d4c17..665587596 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -34,6 +34,7 @@ use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Criteria; use Symfony\Component\Validator\Context\ExecutionContextInterface; +use Symfony\Component\Serializer\Annotation\DiscriminatorMap; /** * Person Class @@ -45,6 +46,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; * columns={"firstName", "lastName"} * )}) * @ORM\HasLifecycleCallbacks() + * @DiscriminatorMap(typeProperty="type", mapping={ + * "person"=Person::class + * }) */ class Person implements HasCenterInterface { diff --git a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodParticipationNormalizer.php b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodParticipationNormalizer.php index 59e430827..a1321b3ef 100644 --- a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodParticipationNormalizer.php +++ b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodParticipationNormalizer.php @@ -41,6 +41,7 @@ class AccompanyingPeriodParticipationNormalizer implements NormalizerInterface, public function supportsNormalization($data, string $format = null): bool { + return false; return $data instanceof AccompanyingPeriodParticipation; } diff --git a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonNormalizer.php b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonNormalizer.php index a0a46c37e..4a9f874de 100644 --- a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonNormalizer.php +++ b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/PersonNormalizer.php @@ -26,6 +26,7 @@ use Chill\PersonBundle\Repository\PersonRepository; use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension; +use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; /** * Serialize a Person entity @@ -33,21 +34,15 @@ use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension; */ class PersonNormalizer implements NormalizerInterface, - NormalizerAwareInterface, - DenormalizerInterface + NormalizerAwareInterface { protected NormalizerInterface $normalizer; - protected PersonRepository $repository; - private ChillEntityRenderExtension $render; - public const GET_PERSON = 'get_person'; - - public function __construct(PersonRepository $repository, ChillEntityRenderExtension $render) + public function __construct(ChillEntityRenderExtension $render) { - $this->repository = $repository; $this->render = $render; } @@ -56,7 +51,7 @@ class PersonNormalizer implements /** @var Person $person */ return [ 'type' => 'person', - 'person_id' => $person->getId(), + 'id' => $person->getId(), 'text' => $this->render->renderString($person), 'firstName' => $person->getFirstName(), 'lastName' => $person->getLastName(), @@ -80,33 +75,11 @@ class PersonNormalizer implements } - public function denormalize($data, string $type, string $format = null, array $context = []): Person - { - if ($context[self::GET_PERSON] ?? true) { - $id = $data['person_id'] ?? null; - if (NULL === $id) { - throw new RuntimeException("missing person_id into person object"); - } - } - /** var Person $person */ - $person = $this->repository->findOneById($id); - - if (NULL === $person) { - throw new UnexpectedValueException("person id not found"); - } - - return $person; - } - public function supportsNormalization($data, string $format = null): bool { return $data instanceof Person; } - public function supportsDenormalization($data, string $type, ?string $format = NULL): bool - { - return Person::class === $type; - } public function setNormalizer(NormalizerInterface $normalizer) { diff --git a/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseApiControllerTest.php b/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseApiControllerTest.php index 99eeb6246..7c60c899a 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseApiControllerTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseApiControllerTest.php @@ -100,14 +100,14 @@ class AccompanyingCourseApiControllerTest extends WebTestCase [], // parameters [], // files [], // server parameters - \json_encode([ 'person_id' => $personId ]) + \json_encode([ 'type' => 'person', 'id' => $personId ]) ); $response = $this->client->getResponse(); $data = \json_decode($response->getContent(), true); $this->assertEquals(200, $response->getStatusCode()); - $this->assertArrayHasKey('person_id', $data); - $this->assertEquals($personId, $data['person_id']); + $this->assertArrayHasKey('id', $data); + $this->assertEquals($personId, $data['id']); // check into database $period = $em->getRepository(AccompanyingPeriod::class) @@ -122,14 +122,14 @@ class AccompanyingCourseApiControllerTest extends WebTestCase [], // parameters [], // files [], // server parameters - \json_encode([ 'thirdparty_id' => $thirdPartyId ]) + \json_encode([ 'type' => 'thirdparty', 'id' => $thirdPartyId ]) ); $response = $this->client->getResponse(); $data = \json_decode($response->getContent(), true); $this->assertEquals(200, $response->getStatusCode()); - $this->assertArrayHasKey('thirdparty_id', $data); - $this->assertEquals($thirdPartyId, $data['thirdparty_id']); + $this->assertArrayHasKey('id', $data); + $this->assertEquals($thirdPartyId, $data['id']); // check into database $period = $em->getRepository(AccompanyingPeriod::class) @@ -152,6 +152,36 @@ class AccompanyingCourseApiControllerTest extends WebTestCase $this->assertNull($period->getRequestor()); } + /** + * + * @dataProvider dataGenerateRandomAccompanyingCourse + */ + public function testAccompanyingPeriodPatch(int $personId, AccompanyingPeriod $period) + { + $initialValueEmergency = $period->isEmergency(); + $em = self::$container->get(EntityManagerInterface::class); + + $this->client->request( + Request::METHOD_PATCH, + sprintf('/api/1.0/person/accompanying-course/%d.json', $period->getId()), + [], // parameters + [], // files + [], // server parameters + \json_encode([ 'type' => 'accompanying_period', 'emergency' => !$initialValueEmergency ]) + ); + $response = $this->client->getResponse(); + + $this->assertEquals(200, $response->getStatusCode()); + $period = $em->getRepository(AccompanyingPeriod::class) + ->find($period->getId()); + $em->refresh($period); + $this->assertEquals(!$initialValueEmergency, $period->isEmergency()); + + // restore the initial valud + $period->setEmergency($initialValueEmergency); + $em->flush(); + } + public function dataGenerateRandomRequestorValidData(): \Iterator { $dataLength = 2; @@ -208,7 +238,7 @@ class AccompanyingCourseApiControllerTest extends WebTestCase [], // parameters [], // files [], // server parameters - \json_encode([ 'person_id' => $personId ]) + \json_encode([ 'type' => 'person', 'id' => $personId ]) ); $response = $this->client->getResponse(); $data = \json_decode($response->getContent(), true); @@ -227,7 +257,7 @@ class AccompanyingCourseApiControllerTest extends WebTestCase // check that the person id is contained $participationsPersonsIds = \array_map( - function($participation) { return $participation->person->person_id; }, + function($participation) { return $participation->person->id; }, $data->participations); $this->assertContains($personId, $participationsPersonsIds); @@ -239,7 +269,7 @@ class AccompanyingCourseApiControllerTest extends WebTestCase [], // parameters [], // files [], // server parameters - \json_encode([ 'person_id' => $personId ]) + \json_encode([ 'type' => 'person', 'id' => $personId ]) ); $response = $this->client->getResponse(); $data = \json_decode($response->getContent(), true); diff --git a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml index dfb7752f5..534e8e161 100644 --- a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml @@ -17,6 +17,9 @@ components: AccompanyingPeriod: type: object properties: + type: + type: string + x-fixed-value: 'accompanying_period' id: type: integer requestorAnonymous: diff --git a/src/Bundle/ChillPersonBundle/config/services.yaml b/src/Bundle/ChillPersonBundle/config/services.yaml index f986a4ccb..d974fb012 100644 --- a/src/Bundle/ChillPersonBundle/config/services.yaml +++ b/src/Bundle/ChillPersonBundle/config/services.yaml @@ -2,7 +2,11 @@ parameters: # cl_chill_person.example.class: Chill\PersonBundle\Example services: - + Chill\PersonBundle\Serializer\Normalizer\: + resource: '../Serializer/Normalizer/' + autowire: true + tags: + - { name: 'serializer.normalizer', priority: 64 } chill.person.form.type.select2maritalstatus: class: Chill\PersonBundle\Form\Type\Select2MaritalStatusType diff --git a/src/Bundle/ChillPersonBundle/config/services/serializer.yaml b/src/Bundle/ChillPersonBundle/config/services/serializer.yaml index 0925cc2ed..922607f8f 100644 --- a/src/Bundle/ChillPersonBundle/config/services/serializer.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/serializer.yaml @@ -1,12 +1,3 @@ --- services: - Chill\PersonBundle\Serializer\Normalizer\PersonNormalizer: - arguments: - $repository: '@Chill\PersonBundle\Repository\PersonRepository' - $render: '@Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension' - tags: - - { name: 'serializer.normalizer', priority: 64 } - - Chill\PersonBundle\Serializer\Normalizer\AccompanyingPeriodParticipationNormalizer: - tags: - - { name: 'serializer.normalizer', priority: 64 } + # note: normalizers are loaded from ../services.yaml diff --git a/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php b/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php index 62d12694b..aa43be265 100644 --- a/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php +++ b/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php @@ -28,6 +28,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Chill\MainBundle\Entity\Center; use Symfony\Component\Validator\Constraints as Assert; use Chill\MainBundle\Entity\Address; +use Symfony\Component\Serializer\Annotation\DiscriminatorMap; /** * ThirdParty is a party recorded in the database. @@ -38,7 +39,9 @@ use Chill\MainBundle\Entity\Address; * * @ORM\Table(name="chill_3party.third_party") * @ORM\Entity(repositoryClass="Chill\ThirdPartyBundle\Repository\ThirdPartyRepository") - * + * @DiscriminatorMap(typeProperty="type", mapping={ + * "thirdparty"=ThirdParty::class + *}) */ class ThirdParty { diff --git a/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php b/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php index 81b5e7f04..203331cb7 100644 --- a/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php +++ b/src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php @@ -6,31 +6,19 @@ use Chill\ThirdPartyBundle\Entity\ThirdParty; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Serializer\Exception\RuntimeException; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository; -class ThirdPartyNormalizer implements NormalizerInterface, DenormalizerInterface, NormalizerAwareInterface +class ThirdPartyNormalizer implements NormalizerInterface, NormalizerAwareInterface { - private ThirdPartyRepository $repository; - use NormalizerAwareTrait; - public function __construct(ThirdPartyRepository $repository) - { - $this->repository= $repository; - } - public function normalize($thirdParty, string $format = null, array $context = []) { /** @var $thirdParty ThirdParty */ $data['type'] = 'thirdparty'; // TODO should be replaced by a "render entity" $data['text'] = $thirdParty->getName(); - $data['thirdparty_id'] = $thirdParty->getId(); + $data['id'] = $thirdParty->getId(); $data['address'] = $this->normalizer->normalize($thirdParty->getAddress(), $format, [ 'address_rendering' => 'short' ]); @@ -42,29 +30,4 @@ class ThirdPartyNormalizer implements NormalizerInterface, DenormalizerInterface return $data instanceof ThirdParty; } - public function denormalize($data, string $type, string $format = null, array $context = []) - { - $thirdParty = $context[AbstractNormalizer::OBJECT_TO_POPULATE] ?? NULL; - if (NULL === $thirdParty) { - $id = $data['thirdparty_id'] ?? NULL; - if (NULL === $id) { - throw new RuntimeException("mission thirdparty_id into body"); - } - - $thirdParty = $this->repository->findOneById($id); - - if (NULL === $thirdParty) { - throw new UnexpectedValueException("thirdparty not found"); - } - } - - return $thirdParty; - } - - public function supportsDenormalization($data, string $type, string $format = null) - { - return ThirdParty::class === $type; - } - - }