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 | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Me | 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 | ||
| 3 | declare(strict_types=1); | |
| 4 | ||
| 5 | namespace App\ApiResource; | |
| 6 | ||
| 7 | use ApiPlatform\Metadata\ApiResource; | |
| 8 | use ApiPlatform\Metadata\Get; | |
| 9 | use ApiPlatform\Metadata\Patch; | |
| 10 | use App\Entity\User; | |
| 11 | use App\Enum\ProfilePart; | |
| 12 | use App\State\MeProcessor; | |
| 13 | use App\State\MeProvider; | |
| 14 | use Symfony\Component\Serializer\Attribute\Groups; | |
| 15 | use Symfony\Component\Validator\Constraints as Assert; | |
| 16 | ||
| 17 | /** | |
| 18 | * GET /api/me: the signed-in user. PATCH /api/me: the user sets the agent name, replaces the | |
| 19 | * custom medals, chooses the visible profile parts or saves the Bannergress sync, the only | |
| 20 | * writable fields. | |
| 21 | */ | |
| 22 | #[ApiResource( | |
| 23 | description: 'The signed-in user. customMedals are the custom medals (anomaly, annual and event medals) as 4e-website stores them: medal keys of its MedalChecker::$customMedals with the tier (anomaly, event; "" for a medal without tiers) or the level 1 (bronze) to 5 (onyx) (annual). visibleParts are the parts of the profile other signed-in users see (agent, avatar, latest_stats, stats_history, custom_medals, bannergress; the others only with agent); visibilityChosen is false until the user chose them; avatar is the Google profile picture as a 100 px JPEG data: URI (null without one) (on /profile or with PATCH), until then everything is private. With PATCH users set their Ingress agent name (the first agent stats uploaded set it when it is not set yet; agent stats are only accepted for this agent, ignoring case; no other user may have it), replace groups of custom medals (a JSON merge patch: groups not sent stay) or choose visibleParts (all of them; without agent none is stored). bannergress is what the app synced from Bannergress (it needs a Bannergress sign-in): the number of banners published (with a mission the agent created), on the to-do and done lists, publishedBanners (all of them), todoBanners (the newest 20) and, written only, doneBanners (the whole done list, read with /api/done-banners); a banner has id, title, missions and picture (relative to https://api.bannergress.com). PATCH replaces it and the server sets syncedAt.', | |
| 24 | operations: [ | |
| 25 | new Get(uriTemplate: '/me', security: "is_granted('ROLE_USER')", provider: MeProvider::class), | |
| 26 | new Patch( | |
| 27 | uriTemplate: '/me', | |
| 28 | collectDenormalizationErrors: true, | |
| 29 | security: "is_granted('ROLE_USER')", | |
| 30 | // /me has no URI variables: without it API Platform would not load the user to patch | |
| 31 | read: true, | |
| 32 | provider: MeProvider::class, | |
| 33 | processor: MeProcessor::class, | |
| 34 | ), | |
| 35 | ], | |
| 36 | normalizationContext: ['groups' => [self::READ]], | |
| 37 | denormalizationContext: ['groups' => [self::WRITE]], | |
| 38 | )] | |
| 39 | final class Me | |
| 40 | { | |
| 41 | public const string READ = 'me:read'; | |
| 42 | ||
| 43 | public const string WRITE = 'me:write'; | |
| 44 | ||
| 45 | public function __construct( | |
| 46 | #[Groups([self::READ])] | |
| 47 | public readonly int $id, | |
| 48 | #[Groups([self::READ])] | |
| 49 | public readonly string $identifier, | |
| 50 | #[Groups([self::READ])] | |
| 51 | public readonly string $role, | |
| 52 | /** Null until the user or the first stats upload sets it; PATCH without it (or null) keeps it. */ | |
| 53 | #[Groups([self::READ, self::WRITE])] | |
| 54 | #[Assert\NotBlank(allowNull: true, normalizer: 'trim')] | |
| 55 | #[Assert\Regex(pattern: User::AGENT_NAME_PATTERN, message: User::AGENT_NAME_INVALID, normalizer: 'trim')] | |
| 56 | public ?string $agentName, | |
| 57 | /** PATCH without it (or null) keeps them. */ | |
| 58 | #[Groups([self::READ, self::WRITE])] | |
| 59 | #[Assert\Valid] | |
| 60 | public ?CustomMedals $customMedals = null, | |
| 61 | /** | |
| 62 | * The profile parts other users see; PATCH replaces them (without the agent part none are | |
| 63 | * stored) and counts as chosen; without it (or null) keeps them. | |
| 64 | * | |
| 65 | * @var list<ProfilePart>|null | |
| 66 | */ | |
| 67 | #[Groups([self::READ, self::WRITE])] | |
| 68 | public ?array $visibleParts = null, | |
| 69 | /** False until the user chose which profile parts other users see (the app asks). */ | |
| 70 | #[Groups([self::READ])] | |
| 71 | public bool $visibilityChosen = false, | |
| 72 | /** The Google profile picture (100 px JPEG data: URI), null without one. */ | |
| 73 | #[Groups([self::READ])] | |
| 74 | public ?string $avatar = null, | |
| 75 | /** What the app synced from Bannergress, null until it did; PATCH replaces it, without it (or null) keeps it. */ | |
| 76 | #[Groups([self::READ, self::WRITE])] | |
| 77 | #[Assert\Valid] | |
| 78 | public ?Bannergress $bannergress = null, | |
| 79 | ) { | |
| 80 | } | |
| 81 | } |