Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.12% covered (success)
94.12%
64 / 68
62.50% covered (warning)
62.50%
5 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
TerminTemplateEndpointTrait
94.12% covered (success)
94.12%
64 / 68
62.50% covered (warning)
62.50%
5 / 8
16.05
0.00% covered (danger)
0.00%
0 / 1
 getEntityData
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
1
 updateEntityWithData
92.59% covered (success)
92.59%
25 / 27
0.00% covered (danger)
0.00%
0 / 1
4.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
 getDurationSeconds
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 getDeadlineEarlierSeconds
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 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\TerminLabel;
6use Olz\Entity\Termine\TerminLocation;
7use Olz\Entity\Termine\TerminTemplate;
8use Olz\Entity\Users\User;
9use Olz\Utils\WithUtilsTrait;
10use PhpTypeScriptApi\HttpError;
11use PhpTypeScriptApi\PhpStan\IsoTime;
12
13/**
14 * @phpstan-type OlzTerminTemplateId int
15 * @phpstan-type OlzTerminTemplateData array{
16 *   startTime?: ?IsoTime,
17 *   durationSeconds?: ?int<0, max>,
18 *   title: string,
19 *   text: string,
20 *   organizerUserId: ?int,
21 *   deadlineEarlierSeconds?: ?int<0, max>,
22 *   deadlineTime?: ?IsoTime,
23 *   shouldPromote: bool,
24 *   newsletter: bool,
25 *   types: array<non-empty-string>,
26 *   locationId?: ?int,
27 *   imageIds: array<non-empty-string>,
28 *   fileIds: array<non-empty-string>,
29 * }
30 */
31trait TerminTemplateEndpointTrait {
32    use WithUtilsTrait;
33
34    /** @return OlzTerminTemplateData */
35    public function getEntityData(TerminTemplate $entity): array {
36        $types_for_api = $this->getTypesForApi($entity->getLabels());
37
38        $valid_image_ids = $this->uploadUtils()->getValidUploadIds($entity->getImageIds());
39        $file_ids = $entity->getStoredFileUploadIds();
40
41        return [
42            'startTime' => IsoTime::fromDateTime($entity->getStartTime()),
43            'durationSeconds' => $this->getDurationSeconds($entity),
44            'title' => $entity->getTitle() ?? '',
45            'text' => $entity->getText() ?? '',
46            'organizerUserId' => $entity->getOrganizerUser()?->getId(),
47            'deadlineEarlierSeconds' => $this->getDeadlineEarlierSeconds($entity),
48            'deadlineTime' => IsoTime::fromDateTime($entity->getDeadlineTime()),
49            'shouldPromote' => $entity->getShouldPromote(),
50            'newsletter' => $entity->getNewsletter(),
51            'types' => $types_for_api,
52            'locationId' => $entity->getLocation()?->getId(),
53            'imageIds' => $valid_image_ids,
54            'fileIds' => $file_ids,
55        ];
56    }
57
58    /** @param OlzTerminTemplateData $input_data */
59    public function updateEntityWithData(TerminTemplate $entity, array $input_data): void {
60        $valid_image_ids = $this->uploadUtils()->getValidUploadIds($input_data['imageIds']);
61        $termin_label_repo = $this->entityManager()->getRepository(TerminLabel::class);
62        $user_repo = $this->entityManager()->getRepository(User::class);
63        $organizer_user_id = $input_data['organizerUserId'] ?? null;
64        $organizer_user = $user_repo->findOneBy(['id' => $organizer_user_id]);
65        $termin_location_repo = $this->entityManager()->getRepository(TerminLocation::class);
66        $location_id = $input_data['locationId'] ?? null;
67        $termin_location = $termin_location_repo->findOneBy(['id' => $location_id]);
68
69        $entity->setStartTime($input_data['startTime'] ?? null);
70        $entity->setDurationSeconds($input_data['durationSeconds'] ?? null);
71        $entity->setTitle($input_data['title']);
72        $entity->setText($input_data['text']);
73        $entity->setOrganizerUser($organizer_user);
74        $entity->setDeadlineEarlierSeconds($input_data['deadlineEarlierSeconds'] ?? null);
75        $entity->setDeadlineTime($input_data['deadlineTime'] ?? null);
76        if (count($valid_image_ids) > 0) {
77            $entity->setShouldPromote($input_data['shouldPromote']);
78        } else {
79            $entity->setShouldPromote(false);
80        }
81        $entity->setNewsletter($input_data['newsletter']);
82        $entity->clearLabels();
83        foreach ($input_data['types'] as $ident) {
84            $termin_label = $termin_label_repo->findOneBy(['ident' => $ident]);
85            if (!$termin_label) {
86                throw new HttpError(400, "No such TerminLabel: {$ident}");
87            }
88            $entity->addLabel($termin_label);
89        }
90        $entity->setLocation($termin_location);
91        $entity->setImageIds($valid_image_ids);
92    }
93
94    /** @param OlzTerminTemplateData $input_data */
95    public function persistUploads(TerminTemplate $entity, array $input_data): void {
96        $this->persistOlzImages($entity, $entity->getImageIds());
97        $this->persistOlzFiles($entity, $input_data['fileIds']);
98    }
99
100    public function editUploads(TerminTemplate $entity): void {
101        $this->editOlzImages($entity, $entity->getImageIds());
102        $this->editOlzFiles($entity);
103    }
104
105    protected function getEntityById(int $id): TerminTemplate {
106        $repo = $this->entityManager()->getRepository(TerminTemplate::class);
107        $entity = $repo->findOneBy(['id' => $id]);
108        if (!$entity) {
109            throw new HttpError(404, "Nicht gefunden.");
110        }
111        return $entity;
112    }
113
114    // ---
115
116    /** @return ?int<0, max> */
117    protected function getDurationSeconds(TerminTemplate $entity): ?int {
118        $number = $entity->getDurationSeconds() ?? null;
119        if ($number < 0) {
120            throw new \Exception("Invalid duration seconds: {$number} ({$entity})");
121        }
122        return $number;
123    }
124
125    /** @return ?int<0, max> */
126    protected function getDeadlineEarlierSeconds(TerminTemplate $entity): ?int {
127        $number = $entity->getDeadlineEarlierSeconds() ?? null;
128        if ($number < 0) {
129            throw new \Exception("Invalid deadline earlier seconds: {$number} ({$entity})");
130        }
131        return $number;
132    }
133
134    /**
135     * @param ?iterable<TerminLabel> $labels
136     *
137     * @return array<non-empty-string>
138     */
139    protected function getTypesForApi(?iterable $labels): array {
140        $types_for_api = [];
141        foreach ($labels ?? [] as $label) {
142            $ident = $label->getIdent();
143            if ($ident) {
144                $types_for_api[] = $ident;
145            }
146        }
147        return $types_for_api;
148    }
149}