mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
add a discrimnator type on onbjects
This commit is contained in:
parent
f7a807473d
commit
91e4d585ff
@ -49,7 +49,12 @@ Ensure that those lines are present in your file `app/config/routing.yml`:
|
|||||||
Create your model
|
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 <https://symfony.com/doc/current/serializer/custom_normalizer.html>`_, you must add `annotations to create serialization groups <https://symfony.com/doc/current/components/serializer.html#attributes-groups>`_. Those groups are, by defaults:
|
||||||
|
|
||||||
|
* :code:`read` for GET requests;
|
||||||
|
* :code:`write` for POST, PUT and PATCH requests
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
@ -57,6 +62,7 @@ Create your model on the usual way:
|
|||||||
|
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\OriginRepository;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\OriginRepository;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Entity(repositoryClass=OriginRepository::class)
|
* @ORM\Entity(repositoryClass=OriginRepository::class)
|
||||||
@ -68,16 +74,19 @@ Create your model on the usual way:
|
|||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
* @ORM\GeneratedValue
|
* @ORM\GeneratedValue
|
||||||
* @ORM\Column(type="integer")
|
* @ORM\Column(type="integer")
|
||||||
|
* @Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="json")
|
* @ORM\Column(type="json")
|
||||||
|
* @Groups({"read", "write"})
|
||||||
*/
|
*/
|
||||||
private $label;
|
private $label;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="date_immutable", nullable=true)
|
* @ORM\Column(type="date_immutable", nullable=true)
|
||||||
|
* @Groups({"read", "write"})
|
||||||
*/
|
*/
|
||||||
private $noActiveAfter;
|
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
|
GET: MY_ROLE_SEE
|
||||||
HEAD: 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
|
Customize the controller
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ use Doctrine\Common\Collections\Collection;
|
|||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
|
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
|
||||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||||
|
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User
|
* User
|
||||||
@ -14,6 +15,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||||||
* @ORM\Entity(repositoryClass="Chill\MainBundle\Repository\UserRepository")
|
* @ORM\Entity(repositoryClass="Chill\MainBundle\Repository\UserRepository")
|
||||||
* @ORM\Table(name="users")
|
* @ORM\Table(name="users")
|
||||||
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region")
|
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region")
|
||||||
|
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||||
|
* "user"=User::class
|
||||||
|
* })
|
||||||
*/
|
*/
|
||||||
class User implements AdvancedUserInterface {
|
class User implements AdvancedUserInterface {
|
||||||
|
|
||||||
|
@ -6,15 +6,21 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
|||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||||
|
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||||
|
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface as SerializerMetadata;
|
||||||
|
|
||||||
|
|
||||||
class DoctrineExistingEntityNormalizer implements DenormalizerInterface
|
class DoctrineExistingEntityNormalizer implements DenormalizerInterface
|
||||||
{
|
{
|
||||||
private EntityManagerInterface $em;
|
private EntityManagerInterface $em;
|
||||||
|
|
||||||
public function __construct(EntityManagerInterface $em)
|
private ClassMetadataFactoryInterface $serializerMetadataFactory;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $em, ClassMetadataFactoryInterface $serializerMetadataFactory)
|
||||||
{
|
{
|
||||||
$this->em = $em;
|
$this->em = $em;
|
||||||
|
$this->serializerMetadataFactory = $serializerMetadataFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function denormalize($data, string $type, string $format = null, array $context = [])
|
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)
|
public function supportsDenormalization($data, string $type, string $format = null)
|
||||||
{
|
{
|
||||||
return \is_array($data)
|
if (FALSE === \is_array($data)) {
|
||||||
&& count($data) === 1
|
return false;
|
||||||
&& \array_key_exists('id', $data)
|
}
|
||||||
&& $this->em->getClassMetadata($type) instanceof ClassMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
class UserNormalizer implements NormalizerInterface
|
||||||
{
|
{
|
||||||
@ -32,8 +32,10 @@ class UserNormalizer implements NormalizerInterface
|
|||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
return [
|
return [
|
||||||
|
'type' => 'user',
|
||||||
'id' => $user->getId(),
|
'id' => $user->getId(),
|
||||||
'username' => $user->getUsername()
|
'username' => $user->getUsername(),
|
||||||
|
'text' => $user->getUsername()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Tests\Serializer\Normalizer;
|
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
|
use Chill\MainBundle\Serializer\Normalizer\DoctrineExistingEntityNormalizer;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
|
||||||
|
|
||||||
|
class DoctrineExistingEntityNormalizerTest extends KernelTestCase
|
||||||
|
{
|
||||||
|
protected DoctrineExistingEntityNormalizer $normalizer;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->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'] ];
|
||||||
|
}
|
||||||
|
}
|
@ -58,12 +58,12 @@ class AccompanyingCourseApiController extends ApiController
|
|||||||
|
|
||||||
if ($errors->count() > 0) {
|
if ($errors->count() > 0) {
|
||||||
// only format accepted
|
// only format accepted
|
||||||
return $this->json($errors);
|
return $this->json($errors, 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getDoctrine()->getManager()->flush();
|
$this->getDoctrine()->getManager()->flush();
|
||||||
|
|
||||||
return $this->json($participation);
|
return $this->json($participation, 200, [], ['groups' => [ 'read' ]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function requestorApi($id, Request $request, string $_format): Response
|
public function requestorApi($id, Request $request, string $_format): Response
|
||||||
@ -102,12 +102,12 @@ class AccompanyingCourseApiController extends ApiController
|
|||||||
|
|
||||||
if ($errors->count() > 0) {
|
if ($errors->count() > 0) {
|
||||||
// only format accepted
|
// only format accepted
|
||||||
return $this->json($errors);
|
return $this->json($errors, 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getDoctrine()->getManager()->flush();
|
$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
|
protected function onPostCheckACL(string $action, Request $request, string $_format, $entity): ?Response
|
||||||
|
@ -34,12 +34,16 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||||
use Chill\MainBundle\Entity\User;
|
use Chill\MainBundle\Entity\User;
|
||||||
use Symfony\Component\Serializer\Annotation\Groups;
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AccompanyingPeriod Class
|
* AccompanyingPeriod Class
|
||||||
*
|
*
|
||||||
* @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriodRepository")
|
* @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriodRepository")
|
||||||
* @ORM\Table(name="chill_person_accompanying_period")
|
* @ORM\Table(name="chill_person_accompanying_period")
|
||||||
|
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||||
|
* "accompanying_period"=AccompanyingPeriod::class
|
||||||
|
* })
|
||||||
*/
|
*/
|
||||||
class AccompanyingPeriod
|
class AccompanyingPeriod
|
||||||
{
|
{
|
||||||
@ -156,6 +160,7 @@ class AccompanyingPeriod
|
|||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
* @ORM\Column(type="string", length=32, nullable=true)
|
* @ORM\Column(type="string", length=32, nullable=true)
|
||||||
|
* @Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $step = self::STEP_DRAFT;
|
private $step = self::STEP_DRAFT;
|
||||||
|
|
||||||
@ -532,7 +537,7 @@ class AccompanyingPeriod
|
|||||||
return $this->requestorPerson;
|
return $this->requestorPerson;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setRequestorPerson(Person $requestorPerson = null): self
|
private function setRequestorPerson(Person $requestorPerson = null): self
|
||||||
{
|
{
|
||||||
$this->requestorPerson = $requestorPerson;
|
$this->requestorPerson = $requestorPerson;
|
||||||
|
|
||||||
@ -544,7 +549,7 @@ class AccompanyingPeriod
|
|||||||
return $this->requestorThirdParty;
|
return $this->requestorThirdParty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setRequestorThirdParty(ThirdParty $requestorThirdParty = null): self
|
private function setRequestorThirdParty(ThirdParty $requestorThirdParty = null): self
|
||||||
{
|
{
|
||||||
$this->requestorThirdParty = $requestorThirdParty;
|
$this->requestorThirdParty = $requestorThirdParty;
|
||||||
|
|
||||||
@ -567,10 +572,10 @@ class AccompanyingPeriod
|
|||||||
* The requestor is either an instance of ThirdParty, or an
|
* The requestor is either an instance of ThirdParty, or an
|
||||||
* instance of Person
|
* instance of Person
|
||||||
*
|
*
|
||||||
* @param $requestor Person|ThirdParty
|
* param $requestor Person|ThirdParty
|
||||||
* @return self
|
* @return self
|
||||||
* @throw UnexpectedValueException if the requestor is not a Person or ThirdParty
|
* @throw UnexpectedValueException if the requestor is not a Person or ThirdParty
|
||||||
*
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
public function setRequestor($requestor): self
|
public function setRequestor($requestor): self
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,8 @@ use Chill\PersonBundle\Repository\AccompanyingPeriodParticipationRepository;
|
|||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AccompanyingPeriodParticipation Class
|
* AccompanyingPeriodParticipation Class
|
||||||
@ -33,6 +35,9 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
* @package Chill\PersonBundle\Entity
|
* @package Chill\PersonBundle\Entity
|
||||||
* @ORM\Entity(repositoryClass=AccompanyingPeriodParticipationRepository::class)
|
* @ORM\Entity(repositoryClass=AccompanyingPeriodParticipationRepository::class)
|
||||||
* @ORM\Table(name="chill_person_accompanying_period_participation")
|
* @ORM\Table(name="chill_person_accompanying_period_participation")
|
||||||
|
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||||
|
* "accompanying_period_participation"=AccompanyingPeriodParticipation::class
|
||||||
|
* })
|
||||||
*/
|
*/
|
||||||
class AccompanyingPeriodParticipation
|
class AccompanyingPeriodParticipation
|
||||||
{
|
{
|
||||||
@ -40,12 +45,14 @@ class AccompanyingPeriodParticipation
|
|||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
* @ORM\GeneratedValue
|
* @ORM\GeneratedValue
|
||||||
* @ORM\Column(type="integer")
|
* @ORM\Column(type="integer")
|
||||||
|
* @Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodParticipations")
|
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodParticipations")
|
||||||
* @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false)
|
* @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false)
|
||||||
|
* @Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $person;
|
private $person;
|
||||||
|
|
||||||
@ -57,11 +64,13 @@ class AccompanyingPeriodParticipation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="date", nullable=false)
|
* @ORM\Column(type="date", nullable=false)
|
||||||
|
* @Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $startDate;
|
private $startDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="date", nullable=true)
|
* @ORM\Column(type="date", nullable=true)
|
||||||
|
* @Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $endDate = null;
|
private $endDate = null;
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ use Doctrine\Common\Collections\Collection;
|
|||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Criteria;
|
use Doctrine\Common\Collections\Criteria;
|
||||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||||
|
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Person Class
|
* Person Class
|
||||||
@ -45,6 +46,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||||||
* columns={"firstName", "lastName"}
|
* columns={"firstName", "lastName"}
|
||||||
* )})
|
* )})
|
||||||
* @ORM\HasLifecycleCallbacks()
|
* @ORM\HasLifecycleCallbacks()
|
||||||
|
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||||
|
* "person"=Person::class
|
||||||
|
* })
|
||||||
*/
|
*/
|
||||||
class Person implements HasCenterInterface
|
class Person implements HasCenterInterface
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,7 @@ class AccompanyingPeriodParticipationNormalizer implements NormalizerInterface,
|
|||||||
|
|
||||||
public function supportsNormalization($data, string $format = null): bool
|
public function supportsNormalization($data, string $format = null): bool
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
return $data instanceof AccompanyingPeriodParticipation;
|
return $data instanceof AccompanyingPeriodParticipation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ use Chill\PersonBundle\Repository\PersonRepository;
|
|||||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
|
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize a Person entity
|
* Serialize a Person entity
|
||||||
@ -33,21 +34,15 @@ use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
|
|||||||
*/
|
*/
|
||||||
class PersonNormalizer implements
|
class PersonNormalizer implements
|
||||||
NormalizerInterface,
|
NormalizerInterface,
|
||||||
NormalizerAwareInterface,
|
NormalizerAwareInterface
|
||||||
DenormalizerInterface
|
|
||||||
{
|
{
|
||||||
|
|
||||||
protected NormalizerInterface $normalizer;
|
protected NormalizerInterface $normalizer;
|
||||||
|
|
||||||
protected PersonRepository $repository;
|
|
||||||
|
|
||||||
private ChillEntityRenderExtension $render;
|
private ChillEntityRenderExtension $render;
|
||||||
|
|
||||||
public const GET_PERSON = 'get_person';
|
public function __construct(ChillEntityRenderExtension $render)
|
||||||
|
|
||||||
public function __construct(PersonRepository $repository, ChillEntityRenderExtension $render)
|
|
||||||
{
|
{
|
||||||
$this->repository = $repository;
|
|
||||||
$this->render = $render;
|
$this->render = $render;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +51,7 @@ class PersonNormalizer implements
|
|||||||
/** @var Person $person */
|
/** @var Person $person */
|
||||||
return [
|
return [
|
||||||
'type' => 'person',
|
'type' => 'person',
|
||||||
'person_id' => $person->getId(),
|
'id' => $person->getId(),
|
||||||
'text' => $this->render->renderString($person),
|
'text' => $this->render->renderString($person),
|
||||||
'firstName' => $person->getFirstName(),
|
'firstName' => $person->getFirstName(),
|
||||||
'lastName' => $person->getLastName(),
|
'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
|
public function supportsNormalization($data, string $format = null): bool
|
||||||
{
|
{
|
||||||
return $data instanceof Person;
|
return $data instanceof Person;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function supportsDenormalization($data, string $type, ?string $format = NULL): bool
|
|
||||||
{
|
|
||||||
return Person::class === $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setNormalizer(NormalizerInterface $normalizer)
|
public function setNormalizer(NormalizerInterface $normalizer)
|
||||||
{
|
{
|
||||||
|
@ -100,14 +100,14 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
|||||||
[], // parameters
|
[], // parameters
|
||||||
[], // files
|
[], // files
|
||||||
[], // server parameters
|
[], // server parameters
|
||||||
\json_encode([ 'person_id' => $personId ])
|
\json_encode([ 'type' => 'person', 'id' => $personId ])
|
||||||
);
|
);
|
||||||
$response = $this->client->getResponse();
|
$response = $this->client->getResponse();
|
||||||
$data = \json_decode($response->getContent(), true);
|
$data = \json_decode($response->getContent(), true);
|
||||||
|
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
$this->assertArrayHasKey('person_id', $data);
|
$this->assertArrayHasKey('id', $data);
|
||||||
$this->assertEquals($personId, $data['person_id']);
|
$this->assertEquals($personId, $data['id']);
|
||||||
|
|
||||||
// check into database
|
// check into database
|
||||||
$period = $em->getRepository(AccompanyingPeriod::class)
|
$period = $em->getRepository(AccompanyingPeriod::class)
|
||||||
@ -122,14 +122,14 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
|||||||
[], // parameters
|
[], // parameters
|
||||||
[], // files
|
[], // files
|
||||||
[], // server parameters
|
[], // server parameters
|
||||||
\json_encode([ 'thirdparty_id' => $thirdPartyId ])
|
\json_encode([ 'type' => 'thirdparty', 'id' => $thirdPartyId ])
|
||||||
);
|
);
|
||||||
$response = $this->client->getResponse();
|
$response = $this->client->getResponse();
|
||||||
$data = \json_decode($response->getContent(), true);
|
$data = \json_decode($response->getContent(), true);
|
||||||
|
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
$this->assertArrayHasKey('thirdparty_id', $data);
|
$this->assertArrayHasKey('id', $data);
|
||||||
$this->assertEquals($thirdPartyId, $data['thirdparty_id']);
|
$this->assertEquals($thirdPartyId, $data['id']);
|
||||||
|
|
||||||
// check into database
|
// check into database
|
||||||
$period = $em->getRepository(AccompanyingPeriod::class)
|
$period = $em->getRepository(AccompanyingPeriod::class)
|
||||||
@ -152,6 +152,36 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
|||||||
$this->assertNull($period->getRequestor());
|
$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
|
public function dataGenerateRandomRequestorValidData(): \Iterator
|
||||||
{
|
{
|
||||||
$dataLength = 2;
|
$dataLength = 2;
|
||||||
@ -208,7 +238,7 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
|||||||
[], // parameters
|
[], // parameters
|
||||||
[], // files
|
[], // files
|
||||||
[], // server parameters
|
[], // server parameters
|
||||||
\json_encode([ 'person_id' => $personId ])
|
\json_encode([ 'type' => 'person', 'id' => $personId ])
|
||||||
);
|
);
|
||||||
$response = $this->client->getResponse();
|
$response = $this->client->getResponse();
|
||||||
$data = \json_decode($response->getContent(), true);
|
$data = \json_decode($response->getContent(), true);
|
||||||
@ -227,7 +257,7 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
|||||||
|
|
||||||
// check that the person id is contained
|
// check that the person id is contained
|
||||||
$participationsPersonsIds = \array_map(
|
$participationsPersonsIds = \array_map(
|
||||||
function($participation) { return $participation->person->person_id; },
|
function($participation) { return $participation->person->id; },
|
||||||
$data->participations);
|
$data->participations);
|
||||||
|
|
||||||
$this->assertContains($personId, $participationsPersonsIds);
|
$this->assertContains($personId, $participationsPersonsIds);
|
||||||
@ -239,7 +269,7 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
|||||||
[], // parameters
|
[], // parameters
|
||||||
[], // files
|
[], // files
|
||||||
[], // server parameters
|
[], // server parameters
|
||||||
\json_encode([ 'person_id' => $personId ])
|
\json_encode([ 'type' => 'person', 'id' => $personId ])
|
||||||
);
|
);
|
||||||
$response = $this->client->getResponse();
|
$response = $this->client->getResponse();
|
||||||
$data = \json_decode($response->getContent(), true);
|
$data = \json_decode($response->getContent(), true);
|
||||||
|
@ -17,6 +17,9 @@ components:
|
|||||||
AccompanyingPeriod:
|
AccompanyingPeriod:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
x-fixed-value: 'accompanying_period'
|
||||||
id:
|
id:
|
||||||
type: integer
|
type: integer
|
||||||
requestorAnonymous:
|
requestorAnonymous:
|
||||||
|
@ -2,7 +2,11 @@ parameters:
|
|||||||
# cl_chill_person.example.class: Chill\PersonBundle\Example
|
# cl_chill_person.example.class: Chill\PersonBundle\Example
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
Chill\PersonBundle\Serializer\Normalizer\:
|
||||||
|
resource: '../Serializer/Normalizer/'
|
||||||
|
autowire: true
|
||||||
|
tags:
|
||||||
|
- { name: 'serializer.normalizer', priority: 64 }
|
||||||
|
|
||||||
chill.person.form.type.select2maritalstatus:
|
chill.person.form.type.select2maritalstatus:
|
||||||
class: Chill\PersonBundle\Form\Type\Select2MaritalStatusType
|
class: Chill\PersonBundle\Form\Type\Select2MaritalStatusType
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
---
|
---
|
||||||
services:
|
services:
|
||||||
Chill\PersonBundle\Serializer\Normalizer\PersonNormalizer:
|
# note: normalizers are loaded from ../services.yaml
|
||||||
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 }
|
|
||||||
|
@ -28,6 +28,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
|||||||
use Chill\MainBundle\Entity\Center;
|
use Chill\MainBundle\Entity\Center;
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
use Chill\MainBundle\Entity\Address;
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ThirdParty is a party recorded in the database.
|
* 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\Table(name="chill_3party.third_party")
|
||||||
* @ORM\Entity(repositoryClass="Chill\ThirdPartyBundle\Repository\ThirdPartyRepository")
|
* @ORM\Entity(repositoryClass="Chill\ThirdPartyBundle\Repository\ThirdPartyRepository")
|
||||||
*
|
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||||
|
* "thirdparty"=ThirdParty::class
|
||||||
|
*})
|
||||||
*/
|
*/
|
||||||
class ThirdParty
|
class ThirdParty
|
||||||
{
|
{
|
||||||
|
@ -6,31 +6,19 @@ use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
|||||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
||||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
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;
|
use NormalizerAwareTrait;
|
||||||
|
|
||||||
public function __construct(ThirdPartyRepository $repository)
|
|
||||||
{
|
|
||||||
$this->repository= $repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function normalize($thirdParty, string $format = null, array $context = [])
|
public function normalize($thirdParty, string $format = null, array $context = [])
|
||||||
{
|
{
|
||||||
/** @var $thirdParty ThirdParty */
|
/** @var $thirdParty ThirdParty */
|
||||||
$data['type'] = 'thirdparty';
|
$data['type'] = 'thirdparty';
|
||||||
// TODO should be replaced by a "render entity"
|
// TODO should be replaced by a "render entity"
|
||||||
$data['text'] = $thirdParty->getName();
|
$data['text'] = $thirdParty->getName();
|
||||||
$data['thirdparty_id'] = $thirdParty->getId();
|
$data['id'] = $thirdParty->getId();
|
||||||
$data['address'] = $this->normalizer->normalize($thirdParty->getAddress(), $format,
|
$data['address'] = $this->normalizer->normalize($thirdParty->getAddress(), $format,
|
||||||
[ 'address_rendering' => 'short' ]);
|
[ 'address_rendering' => 'short' ]);
|
||||||
|
|
||||||
@ -42,29 +30,4 @@ class ThirdPartyNormalizer implements NormalizerInterface, DenormalizerInterface
|
|||||||
return $data instanceof ThirdParty;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user