Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UHF-9613: LinkedEvents getPlacesList fixes #702

Merged
merged 4 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ field_name: field_api_url
entity_type: paragraph
bundle: event_list
label: 'Api URL'
description: 'Add URL from tapahtumat.hel.fi to form a list of events. Example URL: https://tapahtumat.hel.fi/fi/events?categories=museum'
description: 'Add URL from tapahtumat.hel.fi to form a list of events. Example URL: https://tapahtumat.hel.fi/fi/events?categories=museum. If you want to use the location filter, the URL should contain the IDs of all relevant locations. For example: &places=tprek:123,tprek:456'
required: false
translatable: false
default_value: { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ field_name: field_event_location
entity_type: paragraph
bundle: event_list
label: 'Event location'
description: 'Show "event location" filter. Do not use at the same time with the "Remote events" filter.'
description: 'Show "event location" filter. Do not use at the same time with the "Remote events" filter. The API URL field should include all location IDs, otherwise this list will display all active locations.'
required: false
translatable: false
default_value:
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
description: 'Tapahtumat.hel.fi-osoite, jonka perusteella listaus muodostetaan.'
description: 'Tapahtumat.hel.fi-osoite, jonka perusteella listaus muodostetaan. Esimerkki: https://tapahtumat.hel.fi/fi/events?categories=museum. Jos haluat käyttää tapahtumapaikka-suodatinta, URLissa tulee olla mukana tapahtumapaikkojen ID:t. Esim: &places=tprek:123,tprek:456'
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
label: Tapahtumapaikka
description: 'Näytä "tapahtumapaikka" -suodatin. Älä käytä yhtä aikaa "Etätapahtumat" -suodattimen kanssa.'
description: 'Näytä "tapahtumapaikka" -suodatin. Älä käytä yhtä aikaa "Etätapahtumat" -suodattimen kanssa. API URL kentässä tulee olla tapahtumapaikkojen ID:t mukana, muuten listassa näytetään kaikki aktiiviset tapahtumapaikat.'
settings:
on_label: Kyllä
off_label: Ei
9 changes: 9 additions & 0 deletions modules/helfi_react_search/helfi_react_search.install
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,12 @@ function helfi_react_search_update_9005() {
$dispatcher->dispatch(new ReindexScheduledEvent($index, TRUE), SearchApiEvents::REINDEX_SCHEDULED);
}
}

/**
* UHF-9613: Update events list field descriptions and translation.
*/
function helfi_react_search_update_9006() : void {
// Make sure the configurations are correctly installed.
\Drupal::service('helfi_platform_config.config_update_helper')
->update('helfi_react_search');
}
81 changes: 62 additions & 19 deletions modules/helfi_react_search/src/LinkedEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Drupal\helfi_react_search;

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
Expand Down Expand Up @@ -133,51 +134,51 @@ public function getEventsRequest(array $options = [], string $pageSize = '3') :
/**
* Return places from cache or generate list of them.
*
* This function causes slow page load if it fetches places from Linked Events
* API with thousands of events without cache. Function is used in preprocess
* function. It's a known issue but is it possible to get rid of the slowness
* without cache and thousands of events? If this causes problems in the
* future, the function can be re-thinked. More info from old ticket:
* https://helsinkisolutionoffice.atlassian.net/browse/UHF-8163
*
* @param string $url
* @param string $event_url
* The Api url for events.
*
* @return array
* Array of all possible places.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getPlacesList($url) : array {
// Remove keywords from api url not to get detailed keyword data for places.
$url = str_replace('keywords%2C', '', $url);
public function getPlacesList(string $event_url) : array {
$url = $this->formatPlacesUrl($event_url);

if ($data = $this->getFromCache($url)) {
return $data;
}

$result = [];

// Set max page size to reduce amount of requests.
$transformedUrl = Url::fromUri($url);
$transformedUrl->setOption('query', ['page_size' => '100']);
$transformedUrl = $transformedUrl->toString();
// Get location IDs from event URL.
$parsed_url = UrlHelper::parse($event_url);
$places = [];
if (!empty($parsed_url['query']['location'])) {
$places = explode(',', $parsed_url['query']['location']);
}

try {
$response = $this->httpClient->request('GET', $transformedUrl);
$response = $this->httpClient->request('GET', $url);
$body = json_decode($response->getBody()->getContents());
$next = $body->meta->next;
$data = $body->data;

do {
foreach ($data as $item) {
// Bail if no location data.
if (!isset($item->location) || !isset($item->location->id)) {
if (!isset($item->id) || !isset($item->name)) {
continue;
}

if (!array_key_exists($item->location->id, $result)) {
$result[$item->location->id] = $item->location;
// Trim list of locations based on original IDs.
// Has to be done here because places API doesn't accept lists of ids.
if (!empty($places) && !in_array($item->id, $places)) {
continue;
}

if (!array_key_exists($item->id, $result)) {
$result[$item->id] = $item;
}
}

Expand All @@ -201,4 +202,46 @@ public function getPlacesList($url) : array {
return $result;
}

/**
* Format places API URL with query options from events API URL.
*
* - Currently only 'division' option is useful.
* - 'has_upcoming_events' option is used to limit results (from 2k to 700).
* - Places API doesn't accept a list of IDs, so we have to get all results.
* - This is usually still faster than querying each place individually.
*
* @param string $event_url
* Event API URL.
*
* @return string
* Formatted places API URL with query options from event URL.
*/
public function formatPlacesUrl(string $event_url): string {
$url = Url::fromUri(self::API_URL . 'place');

// Add default options to reduce amount of requests.
$defaultOptions = [
'has_upcoming_events' => 'true',
'sort' => 'name',
'page_size' => '100',
];

// Pick up options from event URL.
$options = [];
$parsed_url = UrlHelper::parse($event_url);
if (isset($parsed_url['query']['division'])) {
$options['division'] = $parsed_url['query']['division'];
}

// Add locations to URL for caching purposes.
if (isset($parsed_url['query']['locations'])) {
$options['locations'] = $parsed_url['query']['locations'];
}

$options = array_merge($defaultOptions, $options);
$url->setOption('query', $options);

return $url->toString();
}

}
Loading