Skip to content

Commit 144cc54

Browse files
authored
Merge pull request #166 from os2display/hotfix/display-1019-feed-errors
Hotfix/display 1019 feed errors
2 parents d9b39ba + ae1b9df commit 144cc54

File tree

7 files changed

+415
-405
lines changed

7 files changed

+415
-405
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
- [#166](https://github.com/os2display/display-api-service/pull/166)
8+
- Wrapped feeds in try-catch to avoid throwing errors.
9+
- Added unpublished flow to EventDatabase feed when occurrence returns 404.
10+
- Fixed EventDatabase feed poster subscription parameters not being applied when calling getData().
711
- [#163](https://github.com/os2display/display-api-service/pull/163)
812
Upgraded `itk-dev/openid-connect-bundle` to use code authorization flow. Updated OpenAPI spec accordingly.
913

src/Exceptions/MissingFeedConfigurationException.php

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/Feed/EventDatabaseApiFeedType.php

Lines changed: 174 additions & 145 deletions
Large diffs are not rendered by default.

src/Feed/FeedTypeInterface.php

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@
44

55
use App\Entity\Tenant\Feed;
66
use App\Entity\Tenant\FeedSource;
7-
use App\Exceptions\MissingFeedConfigurationException;
87
use Symfony\Component\HttpFoundation\Request;
9-
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
10-
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
11-
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
12-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
138

149
/**
1510
* Interface that feed types must implement.
@@ -33,13 +28,6 @@ public function getAdminFormOptions(FeedSource $feedSource): array;
3328
*
3429
* @return array
3530
* Array of data
36-
*
37-
* @throws ClientExceptionInterface
38-
* @throws MissingFeedConfigurationException
39-
* @throws RedirectionExceptionInterface
40-
* @throws ServerExceptionInterface
41-
* @throws TransportExceptionInterface
42-
* @throws \JsonException
4331
*/
4432
public function getData(Feed $feed): array;
4533

src/Feed/KobaFeedType.php

Lines changed: 122 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,10 @@
44

55
use App\Entity\Tenant\Feed;
66
use App\Entity\Tenant\FeedSource;
7-
use App\Exceptions\MissingFeedConfigurationException;
87
use App\Service\FeedService;
98
use Psr\Log\LoggerInterface;
109
use Symfony\Component\HttpFoundation\Request;
1110
use Symfony\Component\Uid\Ulid;
12-
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
13-
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
14-
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
15-
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
16-
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
1711
use Symfony\Contracts\HttpClient\HttpClientInterface;
1812

1913
class KobaFeedType implements FeedTypeInterface
@@ -30,89 +24,99 @@ public function __construct(
3024
* @param Feed $feed
3125
*
3226
* @return array
33-
*
34-
* @throws MissingFeedConfigurationException
3527
*/
3628
public function getData(Feed $feed): array
3729
{
38-
$results = [];
30+
try {
31+
$results = [];
3932

40-
$feedSource = $feed->getFeedSource();
41-
$secrets = $feedSource?->getSecrets();
42-
$configuration = $feed->getConfiguration();
33+
$feedSource = $feed->getFeedSource();
34+
$secrets = $feedSource?->getSecrets();
35+
$configuration = $feed->getConfiguration();
4336

44-
if (!isset($secrets['kobaHost']) || !isset($secrets['kobaApiKey'])) {
45-
$this->logger->error('KobaFeedType: "Host" and "ApiKey" not configured.');
37+
if (!isset($secrets['kobaHost']) || !isset($secrets['kobaApiKey'])) {
38+
$this->logger->error('KobaFeedType: "Host" and "ApiKey" not configured.');
4639

47-
throw new MissingFeedConfigurationException('Koba feed "Host" and "ApiKey" not configured');
48-
}
40+
return [];
41+
}
4942

50-
$kobaHost = $secrets['kobaHost'];
51-
$kobaApiKey = $secrets['kobaApiKey'];
52-
$kobaGroup = $secrets['kobaGroup'] ?? 'default';
53-
$filterList = $configuration['filterList'] ?? false;
54-
$rewriteBookedTitles = $configuration['rewriteBookedTitles'] ?? false;
43+
$kobaHost = $secrets['kobaHost'];
44+
$kobaApiKey = $secrets['kobaApiKey'];
45+
$kobaGroup = $secrets['kobaGroup'] ?? 'default';
46+
$filterList = $configuration['filterList'] ?? false;
47+
$rewriteBookedTitles = $configuration['rewriteBookedTitles'] ?? false;
5548

56-
if (!isset($configuration['resources'])) {
57-
$this->logger->error('KobaFeedType: Resources not set.');
49+
if (!isset($configuration['resources'])) {
50+
$this->logger->error('KobaFeedType: Resources not set.');
5851

59-
throw new MissingFeedConfigurationException('resources not configured');
60-
}
52+
return [];
53+
}
6154

62-
$resources = $configuration['resources'];
55+
$resources = $configuration['resources'];
6356

64-
// Round down to the nearest hour.
65-
$from = time() - (time() % 3600);
57+
// Round down to the nearest hour.
58+
$from = time() - (time() % 3600);
6659

67-
// Get bookings for the coming week.
68-
// @TODO: Support for configuring interest period.
69-
$to = $from + 7 * 24 * 60 * 60;
60+
// Get bookings for the coming week.
61+
// @TODO: Support for configuring interest period.
62+
$to = $from + 7 * 24 * 60 * 60;
7063

71-
foreach ($resources as $resource) {
72-
try {
73-
$bookings = $this->getBookingsFromResource($kobaHost, $kobaApiKey, $resource, $kobaGroup, $from, $to);
74-
} catch (\Exception) {
75-
$this->logger->error('KobaFeedType: Get bookings from resources failed.');
76-
continue;
77-
}
64+
foreach ($resources as $resource) {
65+
try {
66+
$bookings = $this->getBookingsFromResource($kobaHost, $kobaApiKey, $resource, $kobaGroup, $from, $to);
67+
} catch (\Throwable $throwable) {
68+
$this->logger->error('KobaFeedType: Get bookings from resources failed. Code: {code}, Message: {message}', [
69+
'code' => $throwable->getCode(),
70+
'message' => $throwable->getMessage(),
71+
]);
72+
continue;
73+
}
7874

79-
foreach ($bookings as $booking) {
80-
$title = $booking['event_name'] ?? '';
75+
foreach ($bookings as $booking) {
76+
$title = $booking['event_name'] ?? '';
8177

82-
// Apply list filter. If enabled it removes all events that do not have (liste) in title.
83-
if ($filterList) {
84-
if (!str_contains($title, '(liste)')) {
85-
continue;
86-
} else {
87-
$title = str_replace('(liste)', '', $title);
78+
// Apply list filter. If enabled it removes all events that do not have (liste) in title.
79+
if ($filterList) {
80+
if (!str_contains($title, '(liste)')) {
81+
continue;
82+
} else {
83+
$title = str_replace('(liste)', '', $title);
84+
}
8885
}
89-
}
9086

91-
// Apply booked title override. If enabled it changes the title to Optaget if it contains (optaget).
92-
if ($rewriteBookedTitles) {
93-
if (str_contains($title, '(optaget)')) {
94-
$title = 'Optaget';
87+
// Apply booked title override. If enabled it changes the title to Optaget if it contains (optaget).
88+
if ($rewriteBookedTitles) {
89+
if (str_contains($title, '(optaget)')) {
90+
$title = 'Optaget';
91+
}
9592
}
96-
}
9793

98-
$results[] = [
99-
'id' => Ulid::generate(),
100-
'title' => $title,
101-
'description' => $booking['event_description'] ?? '',
102-
'startTime' => $booking['start_time'] ?? '',
103-
'endTime' => $booking['end_time'] ?? '',
104-
'resourceTitle' => $booking['resource_alias'] ?? '',
105-
'resourceId' => $booking['resource_id'] ?? '',
106-
];
94+
$results[] = [
95+
'id' => Ulid::generate(),
96+
'title' => $title,
97+
'description' => $booking['event_description'] ?? '',
98+
'startTime' => $booking['start_time'] ?? '',
99+
'endTime' => $booking['end_time'] ?? '',
100+
'resourceTitle' => $booking['resource_alias'] ?? '',
101+
'resourceId' => $booking['resource_id'] ?? '',
102+
];
103+
}
107104
}
108-
}
109105

110-
// Sort bookings by start time.
111-
usort($results, function ($a, $b) {
112-
return strcmp($a['startTime'], $b['startTime']);
113-
});
106+
// Sort bookings by start time.
107+
usort($results, function ($a, $b) {
108+
return strcmp($a['startTime'], $b['startTime']);
109+
});
110+
111+
return $results;
112+
} catch (\Throwable $throwable) {
113+
$this->logger->error('{code}: {message}', [
114+
'code' => $throwable->getCode(),
115+
'message' => $throwable->getMessage(),
116+
]);
117+
}
114118

115-
return $results;
119+
return [];
116120
}
117121

118122
/**
@@ -154,63 +158,64 @@ public function getAdminFormOptions(FeedSource $feedSource): array
154158

155159
/**
156160
* {@inheritDoc}
157-
*
158-
* @throws ClientExceptionInterface
159-
* @throws DecodingExceptionInterface
160-
* @throws RedirectionExceptionInterface
161-
* @throws ServerExceptionInterface
162-
* @throws TransportExceptionInterface
163161
*/
164162
public function getConfigOptions(Request $request, FeedSource $feedSource, string $name): ?array
165163
{
166-
if ('resources' === $name) {
167-
$secrets = $feedSource->getSecrets();
164+
try {
165+
if ('resources' === $name) {
166+
$secrets = $feedSource->getSecrets();
168167

169-
if (!isset($secrets['kobaHost']) || !isset($secrets['kobaApiKey'])) {
170-
return [];
171-
}
168+
if (!isset($secrets['kobaHost']) || !isset($secrets['kobaApiKey'])) {
169+
return [];
170+
}
172171

173-
$kobaHost = $secrets['kobaHost'];
174-
$kobaApiKey = $secrets['kobaApiKey'];
175-
$kobaGroup = $secrets['kobaGroup'] ?? 'default';
172+
$kobaHost = $secrets['kobaHost'];
173+
$kobaApiKey = $secrets['kobaApiKey'];
174+
$kobaGroup = $secrets['kobaGroup'] ?? 'default';
176175

177-
$requestUrl = "$kobaHost/api/resources/group/$kobaGroup";
176+
$requestUrl = "$kobaHost/api/resources/group/$kobaGroup";
178177

179-
$response = $this->client->request('GET', $requestUrl, [
180-
'query' => [
181-
'apikey' => $kobaApiKey,
182-
],
183-
]);
178+
$response = $this->client->request('GET', $requestUrl, [
179+
'query' => [
180+
'apikey' => $kobaApiKey,
181+
],
182+
]);
184183

185-
$content = $response->toArray();
184+
$content = $response->toArray();
186185

187-
$resources = [];
186+
$resources = [];
188187

189-
foreach ($content as $entry) {
190-
// Ignore entries without mail.
191-
if (empty($entry['mail'])) {
192-
continue;
193-
}
188+
foreach ($content as $entry) {
189+
// Ignore entries without mail.
190+
if (empty($entry['mail'])) {
191+
continue;
192+
}
194193

195-
$mail = $entry['mail'];
196-
$alias = !empty($entry['alias']) ? " (${entry['alias']})" : '';
197-
$name = $entry['name'] ?? $mail;
194+
$mail = $entry['mail'];
195+
$alias = !empty($entry['alias']) ? " (${entry['alias']})" : '';
196+
$name = $entry['name'] ?? $mail;
198197

199-
// Make sure a title has been set.
200-
$title = $name.$alias;
198+
// Make sure a title has been set.
199+
$title = $name.$alias;
201200

202-
$resources[] = [
203-
'id' => Ulid::generate(),
204-
'title' => $title,
205-
'value' => $entry['mail'],
206-
];
207-
}
201+
$resources[] = [
202+
'id' => Ulid::generate(),
203+
'title' => $title,
204+
'value' => $entry['mail'],
205+
];
206+
}
208207

209-
usort($resources, function ($a, $b) {
210-
return strcmp($a['title'], $b['title']);
211-
});
208+
usort($resources, function ($a, $b) {
209+
return strcmp($a['title'], $b['title']);
210+
});
212211

213-
return $resources;
212+
return $resources;
213+
}
214+
} catch (\Throwable $throwable) {
215+
$this->logger->error('{code}: {message}', [
216+
'code' => $throwable->getCode(),
217+
'message' => $throwable->getMessage(),
218+
]);
214219
}
215220

216221
return null;
@@ -241,28 +246,18 @@ public function getSupportedFeedOutputType(): string
241246
*
242247
* @return array
243248
*
244-
* @throws ClientExceptionInterface
245-
* @throws DecodingExceptionInterface
246-
* @throws RedirectionExceptionInterface
247-
* @throws ServerExceptionInterface
248-
* @throws TransportExceptionInterface
249+
* @throws \Throwable
249250
*/
250251
private function getBookingsFromResource(string $host, string $apikey, string $resource, string $group, int $from, int $to): array
251252
{
252-
try {
253-
$requestUrl = "$host/api/resources/$resource/group/$group/bookings/from/$from/to/$to";
254-
255-
$response = $this->client->request('GET', $requestUrl, [
256-
'query' => [
257-
'apikey' => $apikey,
258-
],
259-
]);
253+
$requestUrl = "$host/api/resources/$resource/group/$group/bookings/from/$from/to/$to";
260254

261-
return $response->toArray();
262-
} catch (ClientExceptionInterface|DecodingExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface|TransportExceptionInterface $e) {
263-
$this->logger->error('Error building koba data. CODE: '.$e->getCode().', MESSAGE: '.$e->getMessage());
255+
$response = $this->client->request('GET', $requestUrl, [
256+
'query' => [
257+
'apikey' => $apikey,
258+
],
259+
]);
264260

265-
throw $e;
266-
}
261+
return $response->toArray();
267262
}
268263
}

0 commit comments

Comments
 (0)