| @@ -365,6 +365,18 @@ paths: | |||||
| style: form | style: form | ||||
| explode: true | explode: true | ||||
| allowReserved: false | allowReserved: false | ||||
| - | |||||
| name: partnerProduct.product.name | |||||
| in: query | |||||
| description: '' | |||||
| required: false | |||||
| deprecated: false | |||||
| allowEmptyValue: true | |||||
| schema: | |||||
| type: string | |||||
| style: form | |||||
| explode: false | |||||
| allowReserved: false | |||||
| deprecated: false | deprecated: false | ||||
| post: | post: | ||||
| operationId: api_contact_partner_products_post | operationId: api_contact_partner_products_post | ||||
| @@ -4534,6 +4546,10 @@ components: | |||||
| - 'null' | - 'null' | ||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| partnerProduct: | |||||
| readOnly: true | |||||
| description: '?PartnerProduct' | |||||
| $ref: '#/components/schemas/PartnerProduct' | |||||
| product: | product: | ||||
| readOnly: true | readOnly: true | ||||
| description: '?ProductApi' | description: '?ProductApi' | ||||
| @@ -4576,6 +4592,10 @@ components: | |||||
| - 'null' | - 'null' | ||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| partnerProduct: | |||||
| readOnly: true | |||||
| description: '?PartnerProduct' | |||||
| $ref: '#/components/schemas/PartnerProduct.jsonhal' | |||||
| product: | product: | ||||
| readOnly: true | readOnly: true | ||||
| description: '?ProductApi' | description: '?ProductApi' | ||||
| @@ -4632,6 +4652,10 @@ components: | |||||
| - 'null' | - 'null' | ||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| partnerProduct: | |||||
| readOnly: true | |||||
| description: '?PartnerProduct' | |||||
| $ref: '#/components/schemas/PartnerProduct.jsonld' | |||||
| product: | product: | ||||
| readOnly: true | readOnly: true | ||||
| description: '?ProductApi' | description: '?ProductApi' | ||||
| @@ -5418,6 +5442,7 @@ components: | |||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| product: | product: | ||||
| readOnly: true | |||||
| description: '?ProductApi' | description: '?ProductApi' | ||||
| 'owl:maxCardinality': 1 | 'owl:maxCardinality': 1 | ||||
| $ref: '#/components/schemas/Product' | $ref: '#/components/schemas/Product' | ||||
| @@ -5464,6 +5489,7 @@ components: | |||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| product: | product: | ||||
| readOnly: true | |||||
| description: '?ProductApi' | description: '?ProductApi' | ||||
| 'owl:maxCardinality': 1 | 'owl:maxCardinality': 1 | ||||
| $ref: '#/components/schemas/Product.jsonhal' | $ref: '#/components/schemas/Product.jsonhal' | ||||
| @@ -5524,6 +5550,7 @@ components: | |||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| product: | product: | ||||
| readOnly: true | |||||
| description: '?ProductApi' | description: '?ProductApi' | ||||
| 'owl:maxCardinality': 1 | 'owl:maxCardinality': 1 | ||||
| $ref: '#/components/schemas/Product.jsonld' | $ref: '#/components/schemas/Product.jsonld' | ||||
| @@ -5613,6 +5640,7 @@ components: | |||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| numComments: | numComments: | ||||
| readOnly: true | |||||
| type: | type: | ||||
| - integer | - integer | ||||
| - 'null' | - 'null' | ||||
| @@ -5761,6 +5789,7 @@ components: | |||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| numComments: | numComments: | ||||
| readOnly: true | |||||
| type: | type: | ||||
| - integer | - integer | ||||
| - 'null' | - 'null' | ||||
| @@ -5916,6 +5945,7 @@ components: | |||||
| format: iri-reference | format: iri-reference | ||||
| example: 'https://example.com/' | example: 'https://example.com/' | ||||
| numComments: | numComments: | ||||
| readOnly: true | |||||
| type: | type: | ||||
| - integer | - integer | ||||
| - 'null' | - 'null' | ||||
| @@ -6505,6 +6535,11 @@ components: | |||||
| type: | type: | ||||
| - boolean | - boolean | ||||
| - 'null' | - 'null' | ||||
| numTaskNotes: | |||||
| readOnly: true | |||||
| type: | |||||
| - integer | |||||
| - 'null' | |||||
| createdAt: | createdAt: | ||||
| readOnly: true | readOnly: true | ||||
| type: | type: | ||||
| @@ -6609,6 +6644,11 @@ components: | |||||
| type: | type: | ||||
| - boolean | - boolean | ||||
| - 'null' | - 'null' | ||||
| numTaskNotes: | |||||
| readOnly: true | |||||
| type: | |||||
| - integer | |||||
| - 'null' | |||||
| createdAt: | createdAt: | ||||
| readOnly: true | readOnly: true | ||||
| type: | type: | ||||
| @@ -6727,6 +6767,11 @@ components: | |||||
| type: | type: | ||||
| - boolean | - boolean | ||||
| - 'null' | - 'null' | ||||
| numTaskNotes: | |||||
| readOnly: true | |||||
| type: | |||||
| - integer | |||||
| - 'null' | |||||
| createdAt: | createdAt: | ||||
| readOnly: true | readOnly: true | ||||
| type: | type: | ||||
| @@ -45,6 +45,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; | |||||
| // security: 'is_granted("ROLE_ADMIN")', | // security: 'is_granted("ROLE_ADMIN")', | ||||
| // ) | // ) | ||||
| ], | ], | ||||
| order: ['createdAt' => 'DESC'], | |||||
| security: 'is_granted("ROLE_USER")', | security: 'is_granted("ROLE_USER")', | ||||
| provider: EntityToDtoStateProvider::class, | provider: EntityToDtoStateProvider::class, | ||||
| processor: EntityClassDtoStateProcessor::class, | processor: EntityClassDtoStateProcessor::class, | ||||
| @@ -13,6 +13,7 @@ use ApiPlatform\Metadata\ApiFilter; | |||||
| use ApiPlatform\Metadata\ApiProperty; | use ApiPlatform\Metadata\ApiProperty; | ||||
| use ApiPlatform\Metadata\ApiResource; | use ApiPlatform\Metadata\ApiResource; | ||||
| use App\Entity\ContactPartnerProduct; | use App\Entity\ContactPartnerProduct; | ||||
| use App\Entity\PartnerProduct; | |||||
| use App\State\EntityClassDtoStateProcessor; | use App\State\EntityClassDtoStateProcessor; | ||||
| use App\State\EntityToDtoStateProvider; | use App\State\EntityToDtoStateProvider; | ||||
| use ApiPlatform\Metadata\Delete; | use ApiPlatform\Metadata\Delete; | ||||
| @@ -43,7 +44,10 @@ use Symfony\Component\Validator\Constraints\NotBlank; | |||||
| processor: EntityClassDtoStateProcessor::class, | processor: EntityClassDtoStateProcessor::class, | ||||
| stateOptions: new Options(entityClass: ContactPartnerProduct::class), | stateOptions: new Options(entityClass: ContactPartnerProduct::class), | ||||
| )] | )] | ||||
| #[ApiFilter(SearchFilter::class, properties: ['contact' => 'exact'])] | |||||
| #[ApiFilter(SearchFilter::class, properties: [ | |||||
| 'contact' => 'exact', | |||||
| 'partnerProduct.product.name' => 'ipartial', | |||||
| ])] | |||||
| class ContactPartnerProductApi | class ContactPartnerProductApi | ||||
| { | { | ||||
| #[ApiProperty(readable: false, writable: false, identifier: true)] | #[ApiProperty(readable: false, writable: false, identifier: true)] | ||||
| @@ -55,6 +59,22 @@ class ContactPartnerProductApi | |||||
| #[NotBlank] | #[NotBlank] | ||||
| public ?PartnerProductApi $partnerProductIri = null; | public ?PartnerProductApi $partnerProductIri = null; | ||||
| /** | |||||
| * @var $product ?PartnerProduct | |||||
| */ | |||||
| #[ApiProperty( | |||||
| writable: false, | |||||
| readableLink: true, | |||||
| writableLink: false, | |||||
| builtinTypes: [ | |||||
| new Type( | |||||
| 'object', | |||||
| class: PartnerProductApi::class, | |||||
| ) | |||||
| ] | |||||
| )] | |||||
| public ?PartnerProductApi $partnerProduct = null; | |||||
| /** | /** | ||||
| * @var $product ?ProductApi | * @var $product ?ProductApi | ||||
| */ | */ | ||||
| @@ -71,15 +71,16 @@ class PartnerProductApi | |||||
| public ?PartnerApi $partner = null; | public ?PartnerApi $partner = null; | ||||
| #[NotBlank] | #[NotBlank] | ||||
| #[ApiProperty(writable: true)] | |||||
| public ?PartnerApi $partnerIri = null; | public ?PartnerApi $partnerIri = null; | ||||
| /** | /** | ||||
| * @var $product ?ProductApi | * @var $product ?ProductApi | ||||
| */ | */ | ||||
| #[ApiProperty( | #[ApiProperty( | ||||
| writable: true, | |||||
| writable: false, | |||||
| readableLink: true, | readableLink: true, | ||||
| writableLink: true, | |||||
| writableLink: false, | |||||
| builtinTypes: [ | builtinTypes: [ | ||||
| new Type( | new Type( | ||||
| 'object', | 'object', | ||||
| @@ -90,6 +91,7 @@ class PartnerProductApi | |||||
| public ?ProductApi $product = null; | public ?ProductApi $product = null; | ||||
| #[NotBlank] | #[NotBlank] | ||||
| #[ApiProperty(writable: true)] | |||||
| public ?ProductApi $productIri = null; | public ?ProductApi $productIri = null; | ||||
| #[ApiProperty(writable: false)] | #[ApiProperty(writable: false)] | ||||
| @@ -173,6 +173,7 @@ class PostingApi implements OwnerInterface | |||||
| #[Groups(['posting:create'])] | #[Groups(['posting:create'])] | ||||
| public ?SaleApi $saleIri = null; | public ?SaleApi $saleIri = null; | ||||
| #[ApiProperty(writable: false)] | |||||
| public ?int $numComments = null; | public ?int $numComments = null; | ||||
| #[ApiProperty(writable: false)] | #[ApiProperty(writable: false)] | ||||
| @@ -167,6 +167,9 @@ class TaskApi | |||||
| #[Assert\NotNull] | #[Assert\NotNull] | ||||
| public ?bool $completed = null; | public ?bool $completed = null; | ||||
| #[ApiProperty(writable: false)] | |||||
| public ?int $numTaskNotes = null; | |||||
| #[ApiProperty(writable: false)] | #[ApiProperty(writable: false)] | ||||
| public ?\DateTimeImmutable $createdAt = null; | public ?\DateTimeImmutable $createdAt = null; | ||||
| @@ -41,6 +41,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; | |||||
| // security: 'is_granted("ROLE_ADMIN")', | // security: 'is_granted("ROLE_ADMIN")', | ||||
| // ) | // ) | ||||
| ], | ], | ||||
| order: ['createdAt' => 'DESC'], | |||||
| security: 'is_granted("ROLE_USER")', | security: 'is_granted("ROLE_USER")', | ||||
| provider: EntityToDtoStateProvider::class, | provider: EntityToDtoStateProvider::class, | ||||
| processor: EntityClassDtoStateProcessor::class, | processor: EntityClassDtoStateProcessor::class, | ||||
| @@ -53,7 +53,7 @@ class ContactPartnerProductApiToEntityMapper implements MapperInterface | |||||
| assert($contact instanceof Contact); | assert($contact instanceof Contact); | ||||
| assert($partnerProduct instanceof PartnerProduct); | assert($partnerProduct instanceof PartnerProduct); | ||||
| $entity = new PartnerProduct($contact, $partnerProduct); | |||||
| $entity = new ContactPartnerProduct($contact, $partnerProduct); | |||||
| } | } | ||||
| if (!$entity) { | if (!$entity) { | ||||
| @@ -66,9 +66,9 @@ class ContactPartnerProductApiToEntityMapper implements MapperInterface | |||||
| public function populate(object $from, object $to, array $context): object | public function populate(object $from, object $to, array $context): object | ||||
| { | { | ||||
| $dto = $from; | $dto = $from; | ||||
| assert($dto instanceof PartnerProductApi); | |||||
| assert($dto instanceof ContactPartnerProductApi); | |||||
| $entity = $to; | $entity = $to; | ||||
| assert($entity instanceof PartnerProduct); | |||||
| assert($entity instanceof ContactPartnerProduct); | |||||
| return $entity; | return $entity; | ||||
| } | } | ||||
| } | } | ||||
| @@ -47,6 +47,13 @@ class ContactPartnerProductEntityToApiMapper implements MapperInterface | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | MicroMapperInterface::MAX_DEPTH => 1, | ||||
| ]); | ]); | ||||
| $dto->partnerProduct = null; | |||||
| if ($entity->getPartnerProduct() !== null) { | |||||
| $dto->partnerProduct = $this->microMapper->map($entity->getPartnerProduct(), PartnerProductApi::class, [ | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | |||||
| ]); | |||||
| } | |||||
| $dto->product = null; | $dto->product = null; | ||||
| if ($entity->getPartnerProduct() !== null && $entity->getPartnerProduct()->getProduct() !== null) { | if ($entity->getPartnerProduct() !== null && $entity->getPartnerProduct()->getProduct() !== null) { | ||||
| $dto->product = $this->microMapper->map($entity->getPartnerProduct()->getProduct(), ProductApi::class, [ | $dto->product = $this->microMapper->map($entity->getPartnerProduct()->getProduct(), ProductApi::class, [ | ||||
| @@ -34,7 +34,7 @@ class PartnerFollowApiToEntityMapper implements MapperInterface | |||||
| } else { | } else { | ||||
| $user = $this->security->getUser(); | $user = $this->security->getUser(); | ||||
| assert($user instanceof User); | assert($user instanceof User); | ||||
| if ($dto->partner === null) { | |||||
| if ($dto->partnerIri === null) { | |||||
| throw new \Exception('Partner missing'); | throw new \Exception('Partner missing'); | ||||
| } | } | ||||
| $partner = $this->microMapper->map($dto->partnerIri, Partner::class, [ | $partner = $this->microMapper->map($dto->partnerIri, Partner::class, [ | ||||
| @@ -83,6 +83,8 @@ class TaskEntityToApiMapper implements MapperInterface | |||||
| MicroMapperInterface::MAX_DEPTH => 1, | MicroMapperInterface::MAX_DEPTH => 1, | ||||
| ]); | ]); | ||||
| $dto->numTaskNotes = count($entity->getTaskNotes()); | |||||
| $dto->prio = $entity->getPrio(); | $dto->prio = $entity->getPrio(); | ||||
| $dto->completed = $entity->getCompleted(); | $dto->completed = $entity->getCompleted(); | ||||
| $dto->createdAt = $entity->getCreatedAt(); | $dto->createdAt = $entity->getCreatedAt(); | ||||
| @@ -28,12 +28,14 @@ class EntityToDtoStateProvider implements ProviderInterface | |||||
| $resourceClass = $operation->getClass(); | $resourceClass = $operation->getClass(); | ||||
| if ($operation instanceof CollectionOperationInterface) { | if ($operation instanceof CollectionOperationInterface) { | ||||
| $entities = $this->collectionProvider->provide($operation, $uriVariables, $context); | $entities = $this->collectionProvider->provide($operation, $uriVariables, $context); | ||||
| assert($entities instanceof Paginator); | assert($entities instanceof Paginator); | ||||
| $dtos = []; | $dtos = []; | ||||
| foreach ($entities as $entity) { | foreach ($entities as $entity) { | ||||
| $dtos[] = $this->mapEntityToDto($entity, $resourceClass); | $dtos[] = $this->mapEntityToDto($entity, $resourceClass); | ||||
| } | } | ||||
| return $dtos; | |||||
| return new TraversablePaginator( | return new TraversablePaginator( | ||||
| new \ArrayIterator($dtos), | new \ArrayIterator($dtos), | ||||