Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 106 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 1 |
| NewsEndpointTrait | |
0.00% |
0 / 106 |
|
0.00% |
0 / 12 |
1406 | |
0.00% |
0 / 1 |
| getEntityData | |
0.00% |
0 / 25 |
|
0.00% |
0 / 1 |
30 | |||
| updateEntityWithData | |
0.00% |
0 / 35 |
|
0.00% |
0 / 1 |
30 | |||
| persistUploads | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| editUploads | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| getEntityById | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
| getFormat | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| getFormatForApi | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
72 | |||
| getAuthorUserId | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
| getAuthorRoleId | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
| getTerminId | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
| getTagsForDb | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getTagsForApi | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace Olz\News\Endpoints; |
| 4 | |
| 5 | use Olz\Entity\News\NewsEntry; |
| 6 | use Olz\Entity\Roles\Role; |
| 7 | use Olz\Entity\Users\User; |
| 8 | use Olz\Utils\WithUtilsTrait; |
| 9 | use PhpTypeScriptApi\HttpError; |
| 10 | use PhpTypeScriptApi\PhpStan\IsoDateTime; |
| 11 | |
| 12 | /** |
| 13 | * @phpstan-type OlzNewsId int |
| 14 | * @phpstan-type OlzNewsData array{ |
| 15 | * format: OlzNewsFormat, |
| 16 | * authorUserId?: ?int<1, max>, |
| 17 | * authorRoleId?: ?int<1, max>, |
| 18 | * authorName?: ?non-empty-string, |
| 19 | * authorEmail?: ?non-empty-string, |
| 20 | * publishAt?: ?IsoDateTime, |
| 21 | * title: non-empty-string, |
| 22 | * teaser: string, |
| 23 | * content: string, |
| 24 | * externalUrl?: ?non-empty-string, |
| 25 | * tags: array<non-empty-string>, |
| 26 | * terminId?: ?int<1, max>, |
| 27 | * imageIds?: ?array<non-empty-string>, |
| 28 | * fileIds: array<non-empty-string>, |
| 29 | * } |
| 30 | * @phpstan-type OlzNewsFormat 'aktuell'|'kaderblog'|'forum'|'galerie'|'video'|'anonymous' |
| 31 | */ |
| 32 | trait NewsEndpointTrait { |
| 33 | use WithUtilsTrait; |
| 34 | |
| 35 | /** @return OlzNewsData */ |
| 36 | public function getEntityData(NewsEntry $entity): array { |
| 37 | $author_name = $entity->getAuthorName(); |
| 38 | $author_email = $entity->getAuthorEmail(); |
| 39 | $published_date = $entity->getPublishedDate()->format('Y-m-d'); |
| 40 | $published_time = $entity->getPublishedTime()?->format('H:i:s') ?? '00:00:00'; |
| 41 | $tags_for_api = $this->getTagsForApi($entity->getTags()); |
| 42 | $external_url = $entity->getExternalUrl(); |
| 43 | $termin_id = $entity->getTermin(); |
| 44 | |
| 45 | $valid_image_ids = $this->uploadUtils()->getValidUploadIds($entity->getImageIds()); |
| 46 | $file_ids = $entity->getStoredFileUploadIds(); |
| 47 | |
| 48 | return [ |
| 49 | 'format' => $this->getFormatForApi($entity), |
| 50 | 'authorUserId' => $this->getAuthorUserId($entity), |
| 51 | 'authorRoleId' => $this->getAuthorRoleId($entity), |
| 52 | 'authorName' => $author_name ? $author_name : null, |
| 53 | 'authorEmail' => $author_email ? $author_email : null, |
| 54 | 'publishAt' => new IsoDateTime("{$published_date} {$published_time}"), |
| 55 | 'title' => $entity->getTitle() ?: '-', |
| 56 | 'teaser' => $entity->getTeaser() ?? '', |
| 57 | 'content' => $entity->getContent() ?? '', |
| 58 | 'externalUrl' => $external_url ? $external_url : null, |
| 59 | 'tags' => $tags_for_api, |
| 60 | 'terminId' => $this->getTerminId($entity), |
| 61 | 'imageIds' => $valid_image_ids, |
| 62 | 'fileIds' => $file_ids, |
| 63 | ]; |
| 64 | } |
| 65 | |
| 66 | /** @param OlzNewsData $input_data */ |
| 67 | public function updateEntityWithData(NewsEntry $entity, array $input_data): void { |
| 68 | $user_repo = $this->entityManager()->getRepository(User::class); |
| 69 | $role_repo = $this->entityManager()->getRepository(Role::class); |
| 70 | $current_user = $this->authUtils()->getCurrentUser(); |
| 71 | $now = new \DateTime($this->dateUtils()->getIsoNow()); |
| 72 | |
| 73 | $author_user_id = $input_data['authorUserId'] ?? null; |
| 74 | $author_user = $current_user; |
| 75 | if ($author_user_id) { |
| 76 | $author_user = $user_repo->findOneBy(['id' => $author_user_id]); |
| 77 | } |
| 78 | |
| 79 | $author_role_id = $input_data['authorRoleId'] ?? null; |
| 80 | $author_role = null; |
| 81 | if ($author_role_id) { |
| 82 | $is_admin = $this->authUtils()->hasPermission('all'); |
| 83 | $is_authenticated_role = $this->authUtils()->isRoleIdAuthenticated($author_role_id); |
| 84 | if (!$is_authenticated_role && !$is_admin) { |
| 85 | throw new HttpError(403, "Kein Zugriff auf Autor-Rolle!"); |
| 86 | } |
| 87 | $author_role = $role_repo->findOneBy(['id' => $author_role_id]); |
| 88 | } |
| 89 | |
| 90 | $publish_at = $input_data['publishAt'] ?? $now; |
| 91 | |
| 92 | $tags_for_db = $this->getTagsForDb($input_data['tags']); |
| 93 | $valid_image_ids = $this->uploadUtils()->getValidUploadIds($input_data['imageIds'] ?? null); |
| 94 | |
| 95 | $entity->setAuthorUser($author_user); |
| 96 | $entity->setAuthorRole($author_role); |
| 97 | $entity->setAuthorName($input_data['authorName'] ?? null); |
| 98 | $entity->setAuthorEmail($input_data['authorEmail'] ?? null); |
| 99 | $entity->setPublishedDate($publish_at); |
| 100 | $entity->setPublishedTime($publish_at); |
| 101 | $entity->setTitle($input_data['title']); |
| 102 | $entity->setTeaser($input_data['teaser']); |
| 103 | $entity->setContent($input_data['content']); |
| 104 | $entity->setExternalUrl($input_data['externalUrl'] ?? null); |
| 105 | $entity->setTags($tags_for_db); |
| 106 | $entity->setImageIds($valid_image_ids); |
| 107 | // TODO: Do not ignore |
| 108 | $entity->setTermin(0); |
| 109 | $entity->setCounter(0); |
| 110 | $entity->setFormat($this->getFormat($input_data['format'])); |
| 111 | $entity->setNewsletter(true); |
| 112 | } |
| 113 | |
| 114 | /** @param OlzNewsData $input_data */ |
| 115 | public function persistUploads(NewsEntry $entity, array $input_data): void { |
| 116 | $this->persistOlzImages($entity, $entity->getImageIds()); |
| 117 | $this->persistOlzFiles($entity, $input_data['fileIds']); |
| 118 | } |
| 119 | |
| 120 | public function editUploads(NewsEntry $entity): void { |
| 121 | $this->editOlzImages($entity, $entity->getImageIds()); |
| 122 | $this->editOlzFiles($entity); |
| 123 | } |
| 124 | |
| 125 | protected function getEntityById(int $id): NewsEntry { |
| 126 | $news_repo = $this->entityManager()->getRepository(NewsEntry::class); |
| 127 | $entity = $news_repo->findOneBy(['id' => $id]); |
| 128 | if (!$entity) { |
| 129 | throw new HttpError(404, "Nicht gefunden."); |
| 130 | } |
| 131 | return $entity; |
| 132 | } |
| 133 | |
| 134 | // --- |
| 135 | |
| 136 | protected function getFormat(string $format): string { |
| 137 | if ($format === 'anonymous') { |
| 138 | return 'forum'; |
| 139 | } |
| 140 | return $format; |
| 141 | } |
| 142 | |
| 143 | /** @return OlzNewsFormat */ |
| 144 | protected function getFormatForApi(NewsEntry $entity): string { |
| 145 | switch ($entity->getFormat()) { |
| 146 | case 'aktuell': return 'aktuell'; |
| 147 | case 'anonymous': return 'anonymous'; |
| 148 | case 'forum': return 'forum'; |
| 149 | case 'galerie': return 'galerie'; |
| 150 | case 'kaderblog': return 'kaderblog'; |
| 151 | case 'video': return 'video'; |
| 152 | default: throw new \Exception("Unknown news format: {$entity->getFormat()} ({$entity})"); |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | /** @return ?int<1, max> */ |
| 157 | protected function getAuthorUserId(NewsEntry $entity): ?int { |
| 158 | $number = $entity->getAuthorUser()?->getId(); |
| 159 | if ($number === null) { |
| 160 | return null; |
| 161 | } |
| 162 | if ($number < 1) { |
| 163 | throw new \Exception("Invalid author user ID: {$number} ({$entity})"); |
| 164 | } |
| 165 | return $number; |
| 166 | } |
| 167 | |
| 168 | /** @return ?int<1, max> */ |
| 169 | protected function getAuthorRoleId(NewsEntry $entity): ?int { |
| 170 | $number = $entity->getAuthorRole()?->getId(); |
| 171 | if ($number === null) { |
| 172 | return null; |
| 173 | } |
| 174 | if ($number < 1) { |
| 175 | throw new \Exception("Invalid author role ID: {$number} ({$entity})"); |
| 176 | } |
| 177 | return $number; |
| 178 | } |
| 179 | |
| 180 | /** @return ?int<1, max> */ |
| 181 | protected function getTerminId(NewsEntry $entity): ?int { |
| 182 | $number = $entity->getTermin(); |
| 183 | if (!$number) { |
| 184 | return null; |
| 185 | } |
| 186 | if ($number < 1) { |
| 187 | throw new \Exception("Invalid termin ID: {$number} ({$entity})"); |
| 188 | } |
| 189 | return $number; |
| 190 | } |
| 191 | |
| 192 | /** @param array<string> $tags */ |
| 193 | protected function getTagsForDb(?array $tags): string { |
| 194 | return ' '.implode(' ', $tags ?? []).' '; |
| 195 | } |
| 196 | |
| 197 | /** @return array<non-empty-string> */ |
| 198 | protected function getTagsForApi(?string $tags): array { |
| 199 | $tags_string = $tags ?? ''; |
| 200 | $tags_for_api = []; |
| 201 | foreach (explode(' ', $tags_string) as $tag) { |
| 202 | $trimmed = trim($tag); |
| 203 | if ($trimmed) { |
| 204 | $tags_for_api[] = $trimmed; |
| 205 | } |
| 206 | } |
| 207 | return $tags_for_api; |
| 208 | } |
| 209 | } |