14
14
use Symfony \Component \HttpClient \Exception \ClientException ;
15
15
use Symfony \Component \HttpFoundation \Request ;
16
16
use Symfony \Component \HttpFoundation \Response ;
17
+ use Symfony \Component \HttpKernel \Exception \BadRequestHttpException ;
17
18
18
19
/**
19
20
* @see https://github.com/itk-dev/event-database-api
@@ -23,6 +24,10 @@ class EventDatabaseApiV2FeedType implements FeedTypeInterface
23
24
{
24
25
final public const string SUPPORTED_FEED_TYPE = SupportedFeedOutputs::POSTER_OUTPUT ;
25
26
27
+ private const string CACHE_OPTIONS_PREFIX = 'options_ ' ;
28
+ private const string CACHE_EXPIRE_SUFFIX = '_expire ' ;
29
+ private const int CACHE_TTL = 60 * 60 ; // An hour.
30
+
26
31
public function __construct (
27
32
private readonly FeedService $ feedService ,
28
33
private readonly LoggerInterface $ logger ,
@@ -68,37 +73,21 @@ public function getData(Feed $feed): array
68
73
$ locations = $ configuration ['subscriptionPlaceValue ' ] ?? null ;
69
74
$ organizers = $ configuration ['subscriptionOrganizerValue ' ] ?? null ;
70
75
$ tags = $ configuration ['subscriptionTagValue ' ] ?? null ;
71
- $ numberOfItems = $ configuration ['subscriptionNumberValue ' ] ?? 5 ;
76
+ $ numberOfItems = isset ( $ configuration ['subscriptionNumberValue ' ]) ? ( int ) $ configuration [ ' subscriptionNumberValue ' ] : 5 ;
72
77
73
- $ queryParams = [
74
- 'itemsPerPage ' => $ numberOfItems ,
75
- ];
78
+ $ queryParams = [];
76
79
77
80
if (is_array ($ locations ) && count ($ locations ) > 0 ) {
78
- $ queryParams ['location.entityId ' ] = implode (', ' , array_map (static fn ($ location ) => (int ) $ location ['value ' ], $ locations ));
81
+ $ queryParams ['event. location.entityId ' ] = implode (', ' , array_map (static fn ($ location ) => (int ) $ location ['value ' ], $ locations ));
79
82
}
80
83
if (is_array ($ organizers ) && count ($ organizers ) > 0 ) {
81
- $ queryParams ['organizer.entityId ' ] = implode (', ' , array_map (static fn ($ organizer ) => (int ) $ organizer ['value ' ], $ organizers ));
84
+ $ queryParams ['event. organizer.entityId ' ] = implode (', ' , array_map (static fn ($ organizer ) => (int ) $ organizer ['value ' ], $ organizers ));
82
85
}
83
86
if (is_array ($ tags ) && count ($ tags ) > 0 ) {
84
- $ queryParams ['tags ' ] = implode (', ' , array_map (static fn ($ tag ) => (string ) $ tag ['value ' ], $ tags ));
87
+ $ queryParams ['event. tags ' ] = implode (', ' , array_map (static fn ($ tag ) => (string ) $ tag ['value ' ], $ tags ));
85
88
}
86
89
87
- $ queryParams ['occurrences.start ' ] = date ('c ' );
88
- // TODO: Should be based on (end >= now) instead. But not supported by the API.
89
- // $queryParams['occurrences.end'] = date('c');
90
- // @see https://github.com/itk-dev/event-database-api/blob/develop/src/Api/Dto/Event.php
91
-
92
- $ members = $ this ->helper ->request ($ feedSource , 'events ' , $ queryParams );
93
-
94
- $ result = [];
95
-
96
- foreach ($ members as $ member ) {
97
- $ poster = $ this ->helper ->mapFirstOccurrenceToOutput ((object ) $ member );
98
- if (null !== $ poster ) {
99
- $ result [] = $ poster ;
100
- }
101
- }
90
+ $ result = $ this ->getSubscriptionData ($ feedSource , $ queryParams , $ numberOfItems );
102
91
103
92
$ posterOutput = (new PosterOutput ($ result ))->toArray ();
104
93
@@ -112,7 +101,8 @@ public function getData(Feed $feed): array
112
101
if (isset ($ configuration ['singleSelectedOccurrence ' ])) {
113
102
$ occurrenceId = $ configuration ['singleSelectedOccurrence ' ];
114
103
115
- $ members = $ this ->helper ->request ($ feedSource , 'occurrences ' , null , $ occurrenceId );
104
+ $ responseData = $ this ->helper ->request ($ feedSource , 'occurrences ' , null , $ occurrenceId );
105
+ $ members = $ responseData ->{'hydra:member ' };
116
106
117
107
if (empty ($ members )) {
118
108
return [];
@@ -188,6 +178,7 @@ public function getAdminFormOptions(FeedSource $feedSource): array
188
178
$ searchEndpoint = $ this ->feedService ->getFeedSourceConfigUrl ($ feedSource , 'search ' );
189
179
$ entityEndpoint = $ this ->feedService ->getFeedSourceConfigUrl ($ feedSource , 'entity ' );
190
180
$ optionsEndpoint = $ this ->feedService ->getFeedSourceConfigUrl ($ feedSource , 'options ' );
181
+ $ subscriptionEndpoint = $ this ->feedService ->getFeedSourceConfigUrl ($ feedSource , 'subscription ' );
191
182
192
183
return [
193
184
[
@@ -196,6 +187,7 @@ public function getAdminFormOptions(FeedSource $feedSource): array
196
187
'endpointSearch ' => $ searchEndpoint ,
197
188
'endpointEntity ' => $ entityEndpoint ,
198
189
'endpointOption ' => $ optionsEndpoint ,
190
+ 'endpointSubscription ' => $ subscriptionEndpoint ,
199
191
'name ' => 'resources ' ,
200
192
'label ' => 'Vælg resurser ' ,
201
193
'helpText ' => 'Her vælger du hvilke resurser der skal hentes indgange fra. ' ,
@@ -218,7 +210,8 @@ public function getConfigOptions(Request $request, FeedSource $feedSource, strin
218
210
throw new \Exception ('entityType and entityId must not be null ' );
219
211
}
220
212
221
- $ members = $ this ->helper ->request ($ feedSource , $ entityType , null , (int ) $ entityId );
213
+ $ responseData = $ this ->helper ->request ($ feedSource , $ entityType , null , (int ) $ entityId );
214
+ $ members = $ responseData ->{'hydra:member ' };
222
215
223
216
$ result = [];
224
217
@@ -231,24 +224,90 @@ public function getConfigOptions(Request $request, FeedSource $feedSource, strin
231
224
} elseif ('options ' === $ name ) {
232
225
$ entityType = $ request ->query ->get ('entityType ' );
233
226
234
- $ query = [
235
- 'itemsPerPage ' => 50 ,
236
- 'name ' => $ request ->query ->get ('search ' ) ?? '' ,
237
- ];
238
-
239
227
if (null === $ entityType ) {
240
228
throw new \Exception ('entityType must not be null ' );
241
229
}
242
230
243
- $ members = $ this ->helper ->request ($ feedSource , $ entityType , $ query );
231
+ if (!in_array ($ entityType , ['tags ' , 'organizations ' , 'locations ' ])) {
232
+ throw new BadRequestHttpException ('Unsupported entityType: ' .$ entityType );
233
+ }
244
234
245
- $ result = [];
235
+ $ expireCacheItem = $ this ->feedWithoutExpireCache ->getItem ($ this ::CACHE_OPTIONS_PREFIX .$ entityType .$ this ::CACHE_EXPIRE_SUFFIX );
236
+ $ cacheItem = $ this ->feedWithoutExpireCache ->getItem ($ this ::CACHE_OPTIONS_PREFIX .$ entityType );
246
237
247
- foreach ($ members as $ member ) {
248
- $ result [] = $ this ->helper ->toPosterOption ($ member , $ entityType );
238
+ if ($ expireCacheItem ->isHit ()) {
239
+ $ result = $ expireCacheItem ->get ();
240
+
241
+ if ($ result > time ()) {
242
+ if ($ cacheItem ->isHit ()) {
243
+ return $ cacheItem ->get ();
244
+ }
245
+ }
249
246
}
250
247
251
- return $ result ;
248
+ try {
249
+ $ page = 1 ;
250
+ $ results = [];
251
+ $ itemsPerPage = 50 ;
252
+
253
+ do {
254
+ $ query = [
255
+ 'itemsPerPage ' => $ itemsPerPage ,
256
+ 'page ' => $ page ,
257
+ ];
258
+
259
+ $ responseData = $ this ->helper ->request ($ feedSource , $ entityType , $ query );
260
+ $ members = $ responseData ->{'hydra:member ' };
261
+
262
+ foreach ($ members as $ member ) {
263
+ $ results [] = $ this ->helper ->toPosterOption ($ member , $ entityType );
264
+ }
265
+
266
+ if ($ responseData ->{'hydra:totalItems ' } > $ page * $ itemsPerPage ) {
267
+ $ fetchMore = true ;
268
+ $ page = $ page + 1 ;
269
+ } else {
270
+ $ fetchMore = false ;
271
+ }
272
+ } while ($ fetchMore );
273
+
274
+ $ cacheItem ->set ($ results );
275
+ $ this ->feedWithoutExpireCache ->save ($ cacheItem );
276
+
277
+ $ expireCacheItem ->set (time () + $ this ::CACHE_TTL );
278
+ $ this ->feedWithoutExpireCache ->save ($ expireCacheItem );
279
+
280
+ return $ results ;
281
+ } catch (\Exception ) {
282
+ if ($ cacheItem ->isHit ()) {
283
+ return $ cacheItem ->get ();
284
+ } else {
285
+ return [];
286
+ }
287
+ }
288
+ } elseif ('subscription ' === $ name ) {
289
+ $ query = $ request ->query ->all ();
290
+
291
+ $ queryParams = [];
292
+
293
+ if (isset ($ query ['tag ' ])) {
294
+ $ tag = $ query ['tag ' ];
295
+ $ queryParams ['event.tags ' ] = implode (', ' , $ tag );
296
+ }
297
+
298
+ if (isset ($ query ['organization ' ])) {
299
+ $ organizer = $ query ['organization ' ];
300
+ $ queryParams ['event.organizer.entityId ' ] = implode (', ' , $ organizer );
301
+ }
302
+
303
+ if (isset ($ query ['location ' ])) {
304
+ $ location = $ query ['location ' ];
305
+ $ queryParams ['event.location.entityId ' ] = implode (', ' , $ location );
306
+ }
307
+
308
+ $ numberOfItems = isset ($ query ['numberOfItems ' ]) ? (int ) $ query ['numberOfItems ' ] : 10 ;
309
+
310
+ return $ this ->getSubscriptionData ($ feedSource , $ queryParams , $ numberOfItems );
252
311
} elseif ('search ' === $ name ) {
253
312
$ query = $ request ->query ->all ();
254
313
$ queryParams = [];
@@ -267,23 +326,23 @@ public function getConfigOptions(Request $request, FeedSource $feedSource, strin
267
326
268
327
if (isset ($ query ['organization ' ])) {
269
328
$ organizer = $ query ['organization ' ];
270
- $ queryParams ['organizer.entityId ' ] = ( int ) $ organizer ;
329
+ $ queryParams ['organizer.entityId ' ] = $ organizer ;
271
330
}
272
331
273
332
if (isset ($ query ['location ' ])) {
274
333
$ location = $ query ['location ' ];
275
- $ queryParams ['location.entityId ' ] = ( int ) $ location ;
334
+ $ queryParams ['location.entityId ' ] = $ location ;
276
335
}
277
336
278
- $ queryParams ['occurrences.start ' ] = date ('c ' );
279
- // TODO: Should be based on (end >= now) instead. But not supported by the API.
280
- // $queryParams['occurrences.end'] = date('c');
281
- // @see https://github.com/itk-dev/event-database-api/blob/develop/src/Api/Dto/Event.php
337
+ $ queryParams ['occurrences.end ' ] = [
338
+ 'gt ' => date ('c ' ),
339
+ ];
282
340
}
283
341
284
342
$ queryParams ['itemsPerPage ' ] = $ query ['itemsPerPage ' ] ?? 10 ;
285
343
286
- $ members = $ this ->helper ->request ($ feedSource , $ type , $ queryParams );
344
+ $ responseData = $ this ->helper ->request ($ feedSource , $ type , $ queryParams );
345
+ $ members = $ responseData ->{'hydra:member ' };
287
346
288
347
$ result = [];
289
348
@@ -351,4 +410,57 @@ public function getSchema(): array
351
410
'required ' => ['host ' , 'apikey ' ],
352
411
];
353
412
}
413
+
414
+ private function getSubscriptionData (FeedSource $ feedSource , array $ queryParams = [], int $ numberOfItems = 10 ): array
415
+ {
416
+ $ itemsPerPage = 20 ;
417
+ $ page = 1 ;
418
+
419
+ $ result = [];
420
+ $ addedEventIds = [];
421
+
422
+ $ queryParams ['itemsPerPage ' ] = $ itemsPerPage ;
423
+
424
+ $ queryParams ['end ' ] = [
425
+ 'gt ' => date ('c ' ),
426
+ ];
427
+
428
+ do {
429
+ $ queryParams ['page ' ] = $ page ;
430
+
431
+ $ responseData = $ this ->helper ->request ($ feedSource , 'occurrences ' , $ queryParams );
432
+ $ members = $ responseData ->{'hydra:member ' };
433
+
434
+ foreach ($ members as $ member ) {
435
+ // If occurrence.event has not been added already, add it to the result array.
436
+ $ occurrence = $ this ->helper ->mapOccurrenceToOutput ((object ) $ member );
437
+
438
+ if (null == $ occurrence ) {
439
+ continue ;
440
+ }
441
+
442
+ if (!in_array ($ occurrence ->eventId , $ addedEventIds )) {
443
+ $ addedEventIds [] = $ occurrence ->eventId ;
444
+ $ result [] = $ occurrence ;
445
+ }
446
+
447
+ if (count ($ result ) >= $ numberOfItems ) {
448
+ break ;
449
+ }
450
+ }
451
+
452
+ if (count ($ result ) < $ numberOfItems ) {
453
+ if ($ responseData ->{'hydra:totalItems ' } > $ page * $ itemsPerPage ) {
454
+ $ fetchMore = true ;
455
+ $ page = $ page + 1 ;
456
+ } else {
457
+ $ fetchMore = false ;
458
+ }
459
+ } else {
460
+ $ fetchMore = false ;
461
+ }
462
+ } while ($ fetchMore );
463
+
464
+ return $ result ;
465
+ }
354
466
}
0 commit comments