Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.00% covered (success)
95.00%
38 / 40
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
ToggleTerminReactionEndpoint
95.00% covered (success)
95.00%
38 / 40
0.00% covered (danger)
0.00%
0 / 1
14
0.00% covered (danger)
0.00%
0 / 1
 handle
95.00% covered (success)
95.00%
38 / 40
0.00% covered (danger)
0.00%
0 / 1
14
1<?php
2
3namespace Olz\Termine\Endpoints;
4
5use Olz\Api\OlzTypedEndpoint;
6use Olz\Entity\Termine\Termin;
7use Olz\Entity\Termine\TerminReaction;
8use PhpTypeScriptApi\HttpError;
9
10/**
11 * @phpstan-import-type OlzReaction from ListTerminReactionsEndpoint
12 *
13 * @extends OlzTypedEndpoint<
14 *   array{
15 *     terminId: int<1, max>,
16 *     emoji: non-empty-string,
17 *     action: 'on'|'off'|'toggle',
18 *   },
19 *   array{
20 *     result: ?OlzReaction,
21 *   }
22 * >
23 */
24class ToggleTerminReactionEndpoint extends OlzTypedEndpoint {
25    protected function handle(mixed $input): mixed {
26        $has_access = $this->authUtils()->hasPermission('any');
27        $user = $this->authUtils()->getCurrentUser();
28        if (!$has_access || !$user) {
29            throw new HttpError(403, 'Kein Zugriff');
30        }
31        if (mb_strlen($input['emoji']) !== 1) {
32            throw new HttpError(400, 'Ungültiges Emoji');
33        }
34
35        $termin_reaction_repo = $this->entityManager()->getRepository(TerminReaction::class);
36        $reactions = $termin_reaction_repo->findBy([
37            'termin' => $input['terminId'],
38            'emoji' => $input['emoji'],
39            'user' => $user,
40        ]);
41        // Hack for prod not applying the emoji filter correctly.
42        $reactions = array_filter(
43            $reactions,
44            fn ($reaction) => $input['emoji'] === $reaction->getEmoji(),
45        );
46        $has_reactions = count($reactions) > 0;
47        $want_reaction = $input['action'] === 'on' || ($input['action'] === 'toggle' && !$has_reactions);
48        $result = null;
49
50        if (!$has_reactions && $want_reaction) {
51            $termin_repo = $this->entityManager()->getRepository(Termin::class);
52            $termin = $termin_repo->findOneBy(['id' => $input['terminId']]);
53            if (!$termin) {
54                throw new HttpError(400, "Kein solcher Termin");
55            }
56            $reaction = new TerminReaction();
57            $reaction->setTermin($termin);
58            $reaction->setUser($user);
59            $reaction->setEmoji($input['emoji']);
60            $this->entityManager()->persist($reaction);
61            $this->entityManager()->flush();
62            $result = [
63                'userId' => $reaction->getUser()->getId() ?? 0,
64                'name' => $reaction->getUser()->getFullName() ?: '?',
65                'emoji' => $reaction->getEmoji() ?: '?',
66            ];
67        }
68        if ($has_reactions && !$want_reaction) {
69            foreach ($reactions as $reaction) {
70                $this->entityManager()->remove($reaction);
71            }
72            $this->entityManager()->flush();
73        }
74
75        return ['result' => $result];
76    }
77}