Lines 100.00% 1 / 1
Functions and Methods 100.00% 1 / 1
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
TimelineEvent 100.00% 1 / 1 100.00% 1 / 1 1 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
1<?php
2
3declare(strict_types=1);
4
5namespace App\Entity;
6
7use ApiPlatform\Metadata\ApiResource;
8use ApiPlatform\Metadata\Delete;
9use ApiPlatform\Metadata\Get;
10use ApiPlatform\Metadata\GetCollection;
11use ApiPlatform\Metadata\Patch;
12use ApiPlatform\Metadata\Post;
13use App\Repository\TimelineEventRepository;
14use App\Security\Voter\TimelineEventVoter;
15use App\State\TimelineEventProcessor;
16use App\Validator\NoOverlappingTravel;
17use Doctrine\DBAL\Types\Types;
18use Doctrine\ORM\Mapping\Column;
19use Doctrine\ORM\Mapping\Entity;
20use Doctrine\ORM\Mapping\GeneratedValue;
21use Doctrine\ORM\Mapping\Id;
22use Doctrine\ORM\Mapping\JoinColumn;
23use Doctrine\ORM\Mapping\ManyToOne;
24use Symfony\Component\Serializer\Attribute\Context;
25use Symfony\Component\Serializer\Attribute\Groups;
26use Symfony\Component\Serializer\Attribute\Ignore;
27use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
28use Symfony\Component\Validator\Constraints as Assert;
29
30/**
31 * A custom event on the user's timeline (e.g. an anomaly or a mission day), with the stats
32 * uploads; with an end date it lasts from [date] to [endDate] (e.g. a travel; travels cannot overlap). Others see the events with the stats history (ProfilePart::STATS_HISTORY).
33 *
34 * API: the user's own events, newest first (OwnerExtension); the owner adds, changes and deletes them.
35 */
36#[Entity(repositoryClass: TimelineEventRepository::class)]
37#[ApiResource(
38    description: 'Custom events on your timeline: a date, an optional end date (an event over several days, e.g. a travel; travels cannot overlap: 422) and a text. Lists only your own, newest first; other agents see them with your stats history (GET /api/agents/{agentName} events).',
39    operations: [
40        new GetCollection(paginationEnabled: false, security: "is_granted('ROLE_USER')"),
41        new Get(security: "is_granted('".TimelineEventVoter::EDIT."', object)"),
42        new Post(security: "is_granted('ROLE_USER')", processor: TimelineEventProcessor::class),
43        new Patch(security: "is_granted('".TimelineEventVoter::EDIT."', object)"),
44        new Delete(security: "is_granted('".TimelineEventVoter::EDIT."', object)"),
45    ],
46    normalizationContext: ['groups' => [self::READ]],
47    denormalizationContext: ['groups' => [self::WRITE]],
48    order: ['date' => 'DESC', 'id' => 'DESC'],
49)]
50#[NoOverlappingTravel]
51class TimelineEvent
52{
53    public const string READ = 'timeline_event:read';
54
55    public const string WRITE = 'timeline_event:write';
56
57    public const string DATE_FORMAT = 'Y-m-d';
58
59    #[Column, Id, GeneratedValue]
60    #[Groups([self::READ])]
61    public ?int $id = null;
62
63    /** Set on creation: by the form's controller, or TimelineEventProcessor for the API. */
64    #[ManyToOne, JoinColumn(nullable: false, onDelete: 'CASCADE'), Ignore]
65    public ?User $owner = null;
66
67    #[Column(type: Types::DATE_IMMUTABLE)]
68    #[Context([DateTimeNormalizer::FORMAT_KEY => self::DATE_FORMAT])]
69    #[Groups([self::READ, self::WRITE])]
70    #[Assert\NotNull]
71    public ?\DateTimeImmutable $date = null;
72
73    /** The last day of an event over several days; null for a single day. */
74    #[Column(type: Types::DATE_IMMUTABLE, nullable: true)]
75    #[Context([DateTimeNormalizer::FORMAT_KEY => self::DATE_FORMAT])]
76    #[Groups([self::READ, self::WRITE])]
77    #[Assert\GreaterThanOrEqual(propertyPath: 'date', message: 'The end date must not be before the date.')]
78    public ?\DateTimeImmutable $endDate = null;
79
80    #[Column(length: 500)]
81    #[Groups([self::READ, self::WRITE])]
82    #[Assert\NotBlank(normalizer: 'trim'), Assert\Length(max: 500)]
83    public string $text = '';
84
85    #[Column(type: Types::DATETIME_IMMUTABLE)]
86    #[Ignore]
87    public private(set) \DateTimeImmutable $createdAt;
88
89    public function __construct()
90    {
91        $this->createdAt = new \DateTimeImmutable();
92    }
93}