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