<?php
namespace App\Domain\Entity;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use App\Admin\Controller\Api\DeleteAndNotifyPointOfInterestAction;
use App\Application\ApiResources\State\Processor\PointOfInterest\PointOfInterestCreateProcessor;
use App\Application\ApiResources\State\Processor\PointOfInterest\PointOfInterestDeleteProcessor;
use App\Application\ApiResources\State\Processor\PointOfInterest\PointOfInterestUpdateProcessor;
use App\Application\Controller\Api\PointOfInterest\CountCommentAction;
use App\Application\Controller\Api\PointOfInterest\GetJSONRevisionsLogAction;
use App\Application\Controller\Api\PointOfInterest\GetMainRevisionAction;
use App\Application\Controller\Api\PointOfInterest\GetMyPointOfInterestAction;
use App\Application\Controller\Api\PointOfInterest\PostTransferCommentAction;
use App\Application\Controller\Api\PointOfInterest\PostTransferPictureAction;
use App\Application\Controller\Api\PointOfInterest\PostTransferPicturesAction;
use App\Application\Controller\Api\PointOfInterest\SetFavoriteAction;
use App\Application\Dto\PersonPointOfInterest\FavoriteInput;
use App\Application\Dto\PointOfInterest\PointOfInterestInput;
use App\Domain\Entity\Behavior\Identifiable;
use App\Domain\Entity\PointOfInterest\Picture;
use App\Domain\Entity\PointOfInterest\Revision;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\OrderBy;
use Gedmo\SoftDeleteable\Traits\SoftDeleteable;
use Gedmo\Timestampable\Traits\Timestampable;
/**
* Class PointOfInterest
*
* @package App\Domain\Entity
*/
#[
ApiResource(
operations: [
new Delete(security: "is_granted('ROLE_ADMIN')", processor: PointOfInterestDeleteProcessor::class),
new Delete(
uriTemplate: '/point_of_interests/{uuid}/delete_notify',
controller: DeleteAndNotifyPointOfInterestAction::class,
security: "is_granted('ROLE_ADMIN')"
),
new GetCollection(
uriTemplate: '/point_of_interests/mine',
controller: GetMyPointOfInterestAction::class,
openapiContext: [
'summary' => 'Get current user\'s point of interests',
'parameters' => [
[
'name' => 'deletedAt',
'in' => 'query',
'schema' => [
'type' => 'string',
'format' => 'date-time',
],
'description' => 'Date and time of deletion. If set, only deleted point of interests will be returned.',
],
],
'responses' => [
'200' => [
'description' => 'Point of interests list',
'content' => [
'application/json' => [
'schema' => [
'type' => 'object',
'properties' => [
'@context' => [
'type' => 'string',
],
'@id' => [
'type' => 'string',
],
'@type' => [
'type' => 'string',
],
'hydra:member' => [
'type' => 'array',
'items' => [
'type' => 'object',
'properties' => [
'@type' => [
'type' => 'string',
],
'@id' => [
'type' => 'string',
],
'city' => [
'type' => 'string',
],
'mainPicture' => [
'type' => 'string',
],
'title' => [
'type' => 'string',
],
'typeCode' => [
'type' => 'string',
],
'uuid' => [
'type' => 'string',
],
'zipCode' => [
'type' => 'string',
],
],
],
],
],
'example' => [
'@context' => 'string',
'@id' => 'string',
'@type' => 'string',
'hydra:member' => [
[
'@type' => 'string',
'@id' => 'string',
'city' => 'string',
'mainPicture' => 'string',
'title' => 'string',
'typeCode' => 'string',
'uuid' => 'string',
'zipCode' => 'string',
],
],
],
],
],
],
],
],
],
name: 'get_my_points_of_interest',
),
new GetCollection(
uriTemplate: '/point_of_interests/{uuid}/count_comments',
controller: CountCommentAction::class,
name: 'get_total_comments'
),
new Get(),
new Get(
uriTemplate: '/point_of_interests/{uuid}/main_revision',
controller: GetMainRevisionAction::class,
name: 'get_main_revision'
),
new Get(
uriTemplate: '/point_of_interests/{uuid}/revision_log',
controller: GetJSONRevisionsLogAction::class,
name: 'get_revision_json_log'
),
new Post(
inputFormats: ['multipart'],
input: PointOfInterestInput::class,
processor: PointOfInterestCreateProcessor::class
),
new Post(
uriTemplate: '/point_of_interests/{uuid}/transfer_comments',
controller: PostTransferCommentAction::class,
security: "is_granted('ROLE_ADMIN')",
name: 'get_transfer_comment',
),
new Post(
uriTemplate: '/point_of_interests/{uuid}/favorite',
controller: SetFavoriteAction::class,
denormalizationContext: ['groups' => 'favorite_write'],
security: "is_granted('ROLE_USER')",
input: FavoriteInput::class,
),
new Post(
uriTemplate: '/point_of_interests/{uuid}/transfer_pictures',
controller: PostTransferPicturesAction::class,
security: "is_granted('ROLE_ADMIN')",
name: 'get_transfer_pictures'
),
new Post(
uriTemplate: '/point_of_interests/{uuid}/transfer_picture',
controller: PostTransferPictureAction::class,
security: "is_granted('ROLE_ADMIN')",
name: 'get_transfer_picture'
),
new Put(
security: "is_granted('ROLE_ADMIN')",
processor: PointOfInterestUpdateProcessor::class
),
],
normalizationContext: ['groups' => ['point_of_interest_read']],
denormalizationContext: ['groups' => ['point_of_interest_write']],
)
]
class PointOfInterest
{
use Identifiable;
use SoftDeleteable;
use Timestampable;
public const OFFER_TYPE_DISCOVERY = 'discovery';
public const AMOUNT_DISCOVERY = 99.0;
public const VAT_AMOUNT_DISCOVERY = 118.8;
public Collection $awards;
public Collection $comments;
#[OrderBy(['position' => 'asc'])]
public Collection $pictures;
public ?string $remoteId = null;
public ?string $oldId = null;
public Collection $revisions;
public function __construct(
public ?Person $author = null,
public ?Person $referent = null,
public ?Media $mainPicture = null,
#[ApiProperty(openapiContext: ['nullable' => false])]
public float $averageNotation = 0,
public ?DateTime $zhistUpdate = null,
public bool $draft = true,
public ?string $offerType = null,
public ?DateTime $offerEndAt = null,
// For Input Dto only, not doctrine mapped
public ?Revision $revision = null,
public ?bool $isFavorite = false,
public ?string $slug = null,
) {
$this->comments = new ArrayCollection();
$this->pictures = new ArrayCollection();
$this->awards = new ArrayCollection();
$this->revisions = new ArrayCollection();
}
/**
* @param Picture $pointOfInterestPicture
*
* @return void
*/
public function addPointOfInterestPicture(Picture $pointOfInterestPicture): void
{
$this->pictures->add($pointOfInterestPicture);
}
/**
* @param Picture $pointOfInterestPicture
*
* @return void
*/
public function removePointOfInterestPicture(Picture $pointOfInterestPicture): void
{
$this->pictures->removeElement($pointOfInterestPicture);
}
public function removeAward(Award $award): void
{
if (!$this->awards->contains($award)) {
return;
}
$this->awards->removeElement($award);
$award->removePointOfInterest($this);
}
public function addAward(Award $award): void
{
if ($this->awards->contains($award)) {
return;
}
$this->awards->add($award);
$award->addPointOfInterest($this);
}
/**
* @return Collection
*/
public function getAwards(): Collection
{
return $this->awards;
}
/**
* @param Collection $awards
*/
public function setAwards(Collection $awards): void
{
$this->awards = $awards;
}
public function getPictures(): array
{
$pictures = $this->pictures->filter(
fn(Picture $picture) => ($picture->type !== Picture::PICTURE_UNCERTIFIED),
)->getValues();
usort(
$pictures,
fn(Picture $a, Picture $b) => $a->getPosition() <=> $b->getPosition(),
);
return $pictures;
}
/**
* @param Collection $pictures
*/
public function setPictures(Collection $pictures): void
{
$this->pictures = $pictures;
}
public function removePicture(Picture $picture): void
{
if (!$this->pictures->contains($picture)) {
return;
}
$this->pictures->removeElement($picture);
}
public function addPicture(Picture $picture): void
{
if ($this->pictures->contains($picture)) {
return;
}
$this->pictures->add($picture);
}
/**
* @return void
*/
public function removePictures(): void
{
$this->pictures->clear();
}
public function setPicturePosition(Picture $picture, int $position): void
{
$picture->setPosition($position);
}
public function isPro(): bool
{
return $this->offerType !== null && $this->offerEndAt !== null && $this->offerEndAt > new DateTime();
}
}