1414use Symfony \Component \HttpClient \Exception \ClientException ;
1515use Symfony \Component \HttpFoundation \Request ;
1616use Symfony \Component \HttpFoundation \Response ;
17+ use Symfony \Component \HttpKernel \Exception \BadRequestHttpException ;
1718
1819/**
1920 * @see https://github.com/itk-dev/event-database-api
@@ -23,6 +24,10 @@ class EventDatabaseApiV2FeedType implements FeedTypeInterface
2324{
2425 final public const string SUPPORTED_FEED_TYPE = SupportedFeedOutputs::POSTER_OUTPUT ;
2526
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+
2631 public function __construct (
2732 private readonly FeedService $ feedService ,
2833 private readonly LoggerInterface $ logger ,
@@ -68,37 +73,21 @@ public function getData(Feed $feed): array
6873 $ locations = $ configuration ['subscriptionPlaceValue ' ] ?? null ;
6974 $ organizers = $ configuration ['subscriptionOrganizerValue ' ] ?? null ;
7075 $ tags = $ configuration ['subscriptionTagValue ' ] ?? null ;
71- $ numberOfItems = $ configuration ['subscriptionNumberValue ' ] ?? 5 ;
76+ $ numberOfItems = isset ( $ configuration ['subscriptionNumberValue ' ]) ? ( int ) $ configuration [ ' subscriptionNumberValue ' ] : 5 ;
7277
73- $ queryParams = [
74- 'itemsPerPage ' => $ numberOfItems ,
75- ];
78+ $ queryParams = [];
7679
7780 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 ));
7982 }
8083 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 ));
8285 }
8386 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 ));
8588 }
8689
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 );
10291
10392 $ posterOutput = (new PosterOutput ($ result ))->toArray ();
10493
@@ -112,7 +101,8 @@ public function getData(Feed $feed): array
112101 if (isset ($ configuration ['singleSelectedOccurrence ' ])) {
113102 $ occurrenceId = $ configuration ['singleSelectedOccurrence ' ];
114103
115- $ members = $ this ->helper ->request ($ feedSource , 'occurrences ' , null , $ occurrenceId );
104+ $ responseData = $ this ->helper ->request ($ feedSource , 'occurrences ' , null , $ occurrenceId );
105+ $ members = $ responseData ->{'hydra:member ' };
116106
117107 if (empty ($ members )) {
118108 return [];
@@ -188,6 +178,7 @@ public function getAdminFormOptions(FeedSource $feedSource): array
188178 $ searchEndpoint = $ this ->feedService ->getFeedSourceConfigUrl ($ feedSource , 'search ' );
189179 $ entityEndpoint = $ this ->feedService ->getFeedSourceConfigUrl ($ feedSource , 'entity ' );
190180 $ optionsEndpoint = $ this ->feedService ->getFeedSourceConfigUrl ($ feedSource , 'options ' );
181+ $ subscriptionEndpoint = $ this ->feedService ->getFeedSourceConfigUrl ($ feedSource , 'subscription ' );
191182
192183 return [
193184 [
@@ -196,6 +187,7 @@ public function getAdminFormOptions(FeedSource $feedSource): array
196187 'endpointSearch ' => $ searchEndpoint ,
197188 'endpointEntity ' => $ entityEndpoint ,
198189 'endpointOption ' => $ optionsEndpoint ,
190+ 'endpointSubscription ' => $ subscriptionEndpoint ,
199191 'name ' => 'resources ' ,
200192 'label ' => 'Vælg resurser ' ,
201193 'helpText ' => 'Her vælger du hvilke resurser der skal hentes indgange fra. ' ,
@@ -218,7 +210,8 @@ public function getConfigOptions(Request $request, FeedSource $feedSource, strin
218210 throw new \Exception ('entityType and entityId must not be null ' );
219211 }
220212
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 ' };
222215
223216 $ result = [];
224217
@@ -231,24 +224,90 @@ public function getConfigOptions(Request $request, FeedSource $feedSource, strin
231224 } elseif ('options ' === $ name ) {
232225 $ entityType = $ request ->query ->get ('entityType ' );
233226
234- $ query = [
235- 'itemsPerPage ' => 50 ,
236- 'name ' => $ request ->query ->get ('search ' ) ?? '' ,
237- ];
238-
239227 if (null === $ entityType ) {
240228 throw new \Exception ('entityType must not be null ' );
241229 }
242230
243- $ members = $ this ->helper ->request ($ feedSource , $ entityType , $ query );
231+ if (!in_array ($ entityType , ['tags ' , 'organizations ' , 'locations ' ])) {
232+ throw new BadRequestHttpException ('Unsupported entityType: ' .$ entityType );
233+ }
244234
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 );
246237
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+ }
249246 }
250247
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 );
252311 } elseif ('search ' === $ name ) {
253312 $ query = $ request ->query ->all ();
254313 $ queryParams = [];
@@ -267,23 +326,23 @@ public function getConfigOptions(Request $request, FeedSource $feedSource, strin
267326
268327 if (isset ($ query ['organization ' ])) {
269328 $ organizer = $ query ['organization ' ];
270- $ queryParams ['organizer.entityId ' ] = ( int ) $ organizer ;
329+ $ queryParams ['organizer.entityId ' ] = $ organizer ;
271330 }
272331
273332 if (isset ($ query ['location ' ])) {
274333 $ location = $ query ['location ' ];
275- $ queryParams ['location.entityId ' ] = ( int ) $ location ;
334+ $ queryParams ['location.entityId ' ] = $ location ;
276335 }
277336
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+ ];
282340 }
283341
284342 $ queryParams ['itemsPerPage ' ] = $ query ['itemsPerPage ' ] ?? 10 ;
285343
286- $ members = $ this ->helper ->request ($ feedSource , $ type , $ queryParams );
344+ $ responseData = $ this ->helper ->request ($ feedSource , $ type , $ queryParams );
345+ $ members = $ responseData ->{'hydra:member ' };
287346
288347 $ result = [];
289348
@@ -351,4 +410,57 @@ public function getSchema(): array
351410 'required ' => ['host ' , 'apikey ' ],
352411 ];
353412 }
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+ }
354466}
0 commit comments