Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.30% covered (success)
96.30%
78 / 81
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
TerminEndpointTrait
96.30% covered (success)
96.30%
78 / 81
83.33% covered (warning)
83.33%
5 / 6
17
0.00% covered (danger)
0.00%
0 / 1
 getEntityData
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
5
 updateEntityWithData
92.68% covered (success)
92.68%
38 / 41
0.00% covered (danger)
0.00%
0 / 1
5.01
 persistUploads
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 editUploads
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getEntityById
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getTypesForApi
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3namespace Olz\Termine\Endpoints;
4
5use Olz\Entity\Termine\Termin;
6use Olz\Entity\Termine\TerminLabel;
7use Olz\Entity\Termine\TerminLocation;
8use Olz\Entity\Termine\TerminTemplate;
9use Olz\Entity\Users\User;
10use Olz\Utils\MapUtils;
11use Olz\Utils\WithUtilsTrait;
12use PhpTypeScriptApi\HttpError;
13use PhpTypeScriptApi\PhpStan\IsoDate;
14use PhpTypeScriptApi\PhpStan\IsoDateTime;
15use PhpTypeScriptApi\PhpStan\IsoTime;
16
17/**
18 * @phpstan-type OlzTerminId int
19 *
20 * @phpstan-import-type OlzLocationCoordinates from MapUtils
21 *
22 * @phpstan-type OlzTerminData array{
23 *   fromTemplateId?: ?int,
24 *   startDate?: ?IsoDate,
25 *   startTime?: ?IsoTime,
26 *   endDate?: ?IsoDate,
27 *   endTime?: ?IsoTime,
28 *   title?: ?non-empty-string,
29 *   text: string,
30 *   organizerUserId: ?int,
31 *   deadline?: ?IsoDateTime,
32 *   shouldPromote: bool,
33 *   newsletter: bool,
34 *   solvId?: ?int,
35 *   types: array<non-empty-string>,
36 *   locationId?: ?int,
37 *   location?: ?OlzLocationCoordinates,
38 *   parentTerminId?: ?int,
39 *   imageIds: array<non-empty-string>,
40 *   fileIds: array<non-empty-string>,
41 * }
42 */
43trait TerminEndpointTrait {
44    use WithUtilsTrait;
45
46    /** @return OlzTerminData */
47    public function getEntityData(Termin $entity): array {
48        $types_for_api = $this->getTypesForApi($entity->getLabels());
49
50        $valid_image_ids = $this->uploadUtils()->getValidUploadIds($entity->getImageIds());
51        $file_ids = $entity->getStoredFileUploadIds();
52
53        return [
54            'fromTemplateId' => $entity->getFromTemplate()?->getId(),
55            'startDate' => IsoDate::fromDateTime($entity->getStartDate()),
56            'startTime' => IsoTime::fromDateTime($entity->getStartTime()),
57            'endDate' => IsoDate::fromDateTime($entity->getEndDate()),
58            'endTime' => IsoTime::fromDateTime($entity->getEndTime()),
59            'title' => $entity->getTitle() ?: '-',
60            'text' => $entity->getText() ?? '',
61            'organizerUserId' => $entity->getOrganizerUser()?->getId(),
62            'deadline' => IsoDateTime::fromDateTime($entity->getDeadline()),
63            'shouldPromote' => $entity->getShouldPromote(),
64            'newsletter' => $entity->getNewsletter(),
65            'solvId' => $entity->getSolvId() ?: null,
66            'types' => $types_for_api,
67            'locationId' => $entity->getLocation()?->getId(),
68            'location' => ($entity->getLatitude() !== null && $entity->getLongitude() !== null) ? [
69                'latitude' => $entity->getLatitude(),
70                'longitude' => $entity->getLongitude(),
71            ] : null,
72            'parentTerminId' => $entity->getParentTermin()?->getId(),
73            'imageIds' => $valid_image_ids,
74            'fileIds' => $file_ids,
75        ];
76    }
77
78    /** @param OlzTerminData $input_data */
79    public function updateEntityWithData(Termin $entity, array $input_data): void {
80        $valid_image_ids = $this->uploadUtils()->getValidUploadIds($input_data['imageIds']);
81        $termin_template_repo = $this->entityManager()->getRepository(TerminTemplate::class);
82        $from_template_id = $input_data['fromTemplateId'] ?? null;
83        $termin_template = $termin_template_repo->findOneBy(['id' => $from_template_id]);
84        $termin_label_repo = $this->entityManager()->getRepository(TerminLabel::class);
85        $user_repo = $this->entityManager()->getRepository(User::class);
86        $organizer_user_id = $input_data['organizerUserId'] ?? null;
87        $organizer_user = $user_repo->findOneBy(['id' => $organizer_user_id]);
88        $termin_location_repo = $this->entityManager()->getRepository(TerminLocation::class);
89        $location_id = $input_data['locationId'] ?? null;
90        $termin_location = $termin_location_repo->findOneBy(['id' => $location_id]);
91        $termin_repo = $this->entityManager()->getRepository(Termin::class);
92        $parent_termin_id = $input_data['parentTerminId'] ?? null;
93        $parent_termin = $termin_repo->findOneBy(['id' => $parent_termin_id]);
94
95        $entity->setFromTemplate($termin_template);
96        $entity->setStartDate($input_data['startDate'] ?? new \DateTime());
97        $entity->setStartTime($input_data['startTime'] ?? null);
98        $entity->setEndDate($input_data['endDate'] ?? null);
99        $entity->setEndTime($input_data['endTime'] ?? null);
100        $entity->setTitle($input_data['title'] ?? null);
101        $entity->setText($input_data['text']);
102        $entity->setOrganizerUser($organizer_user);
103        $entity->setDeadline($input_data['deadline'] ?? null);
104        if (count($valid_image_ids) > 0) {
105            $entity->setShouldPromote($input_data['shouldPromote']);
106        } else {
107            $entity->setShouldPromote(false);
108        }
109        $entity->setNewsletter($input_data['newsletter']);
110        $entity->setSolvId($input_data['solvId'] ?? null);
111        $entity->clearLabels();
112        foreach ($input_data['types'] as $ident) {
113            $termin_label = $termin_label_repo->findOneBy(['ident' => $ident]);
114            if (!$termin_label) {
115                throw new HttpError(400, "No such TerminLabel: {$ident}");
116            }
117            $entity->addLabel($termin_label);
118        }
119        $entity->setLocation($termin_location);
120        $entity->setLatitude($input_data['location']['latitude'] ?? null);
121        $entity->setLongitude($input_data['location']['longitude'] ?? null);
122        $entity->setParentTermin($parent_termin);
123        $entity->setImageIds($valid_image_ids);
124
125        if ($entity->getSolvId() !== null) {
126            $this->termineUtils()->updateTerminFromSolvEvent($entity);
127        }
128    }
129
130    /** @param OlzTerminData $input_data */
131    public function persistUploads(Termin $entity, array $input_data): void {
132        $this->persistOlzImages($entity, $entity->getImageIds());
133        $this->persistOlzFiles($entity, $input_data['fileIds']);
134    }
135
136    public function editUploads(Termin $entity): void {
137        $this->editOlzImages($entity, $entity->getImageIds());
138        $this->editOlzFiles($entity);
139    }
140
141    protected function getEntityById(int $id): Termin {
142        $repo = $this->entityManager()->getRepository(Termin::class);
143        $entity = $repo->findOneBy(['id' => $id]);
144        if (!$entity) {
145            throw new HttpError(404, "Nicht gefunden.");
146        }
147        return $entity;
148    }
149
150    // ---
151
152    /**
153     * @param ?iterable<TerminLabel> $labels
154     *
155     * @return array<non-empty-string>
156     */
157    protected function getTypesForApi(?iterable $labels): array {
158        $types_for_api = [];
159        foreach ($labels ?? [] as $label) {
160            $ident = $label->getIdent();
161            if ($ident) {
162                $types_for_api[] = $ident;
163            }
164        }
165        return $types_for_api;
166    }
167}