Lines 100.00% 2 / 2
Functions and Methods 100.00% 2 / 2
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
DoneBanner 100.00% 2 / 2 100.00% 2 / 2 3 100.00% 1 / 1
 getUrl 100.00% 1 / 1 100.00% 1 / 1 1
 getPictureUrl 100.00% 1 / 1 100.00% 1 / 1 2
1<?php
2
3declare(strict_types=1);
4
5namespace App\Entity;
6
7use ApiPlatform\Metadata\ApiResource;
8use ApiPlatform\Metadata\Get;
9use ApiPlatform\Metadata\GetCollection;
10use ApiPlatform\Metadata\Patch;
11use App\ApiResource\Bannergress;
12use App\Repository\DoneBannerRepository;
13use App\Security\Voter\DoneBannerVoter;
14use Doctrine\DBAL\Types\Types;
15use Doctrine\ORM\Mapping\Column;
16use Doctrine\ORM\Mapping\Entity;
17use Doctrine\ORM\Mapping\GeneratedValue;
18use Doctrine\ORM\Mapping\Id;
19use Doctrine\ORM\Mapping\JoinColumn;
20use Doctrine\ORM\Mapping\ManyToOne;
21use Doctrine\ORM\Mapping\UniqueConstraint;
22use Symfony\Component\Serializer\Attribute\Context;
23use Symfony\Component\Serializer\Attribute\Groups;
24use Symfony\Component\Serializer\Attribute\Ignore;
25use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
26
27/**
28 * A banner on the user's Bannergress done list, as the app synced it (Bannergress sync, see
29 * BannergressSync), with the day the user did it: the user sets [doneAt], a sync keeps it (an
30 * event banner without a day gets the event's first day).
31 * Banners with a day are on the timeline. Others see them with the Bannergress part.
32 *
33 * API: the user's own, newest on the list first (OwnerExtension); the owner sets the day.
34 */
35#[Entity(repositoryClass: DoneBannerRepository::class)]
36#[UniqueConstraint(name: 'done_banner_owner_banner', fields: ['owner', 'bannerId'])]
37#[ApiResource(
38    description: 'The banners on your Bannergress done list, as the app synced them (PATCH /api/me bannergress doneBanners), newest on the list first: bannerId (the Bannergress id), title, missions, picture (relative to https://api.bannergress.com), startLatitude / startLongitude (where it starts) and doneAt, the day you did it (Y-m-d, null until you set it; banners with a day are on your timeline). PATCH sets doneAt; a sync keeps it, and gives an event banner without a day the first day of the event (doneBanners eventStartDate).',
39    operations: [
40        new GetCollection(paginationEnabled: false, security: "is_granted('ROLE_USER')"),
41        new Get(security: "is_granted('".DoneBannerVoter::EDIT."', object)"),
42        new Patch(security: "is_granted('".DoneBannerVoter::EDIT."', object)"),
43    ],
44    normalizationContext: ['groups' => [self::READ]],
45    denormalizationContext: ['groups' => [self::WRITE]],
46    order: ['position' => 'ASC'],
47)]
48class DoneBanner
49{
50    public const string READ = 'done_banner:read';
51
52    public const string WRITE = 'done_banner:write';
53
54    #[Column, Id, GeneratedValue]
55    #[Groups([self::READ])]
56    public ?int $id = null;
57
58    #[ManyToOne, JoinColumn(nullable: false, onDelete: 'CASCADE'), Ignore]
59    public ?User $owner = null;
60
61    /** The Bannergress id, e.g. cologne-cathedral-57d4. */
62    #[Column(length: 200)]
63    #[Groups([self::READ])]
64    public string $bannerId = '';
65
66    #[Column(length: 200)]
67    #[Groups([self::READ])]
68    public string $title = '';
69
70    #[Column]
71    #[Groups([self::READ])]
72    public int $missions = 0;
73
74    /** Relative to Bannergress::PICTURE_BASE. */
75    #[Column(length: 150, nullable: true)]
76    #[Groups([self::READ])]
77    public ?string $picture = null;
78
79    /** Where the banner starts. */
80    #[Column(nullable: true)]
81    #[Groups([self::READ])]
82    public ?float $startLatitude = null;
83
84    #[Column(nullable: true)]
85    #[Groups([self::READ])]
86    public ?float $startLongitude = null;
87
88    /** On the done list: 0 is the newest. */
89    #[Column]
90    #[Ignore]
91    public int $position = 0;
92
93    /** The day the user did it; null until set. */
94    #[Column(type: Types::DATE_IMMUTABLE, nullable: true)]
95    #[Context([DateTimeNormalizer::FORMAT_KEY => TimelineEvent::DATE_FORMAT])]
96    #[Groups([self::READ, self::WRITE])]
97    public ?\DateTimeImmutable $doneAt = null;
98
99    #[Ignore]
100    public function getUrl(): string
101    {
102        return Bannergress::BANNER_BASE.\rawurlencode($this->bannerId);
103    }
104
105    #[Ignore]
106    public function getPictureUrl(): ?string
107    {
108        return null === $this->picture ? null : Bannergress::PICTURE_BASE.$this->picture;
109    }
110}