Skip to content
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
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"drupal/hdbt_admin": "^3.0",
"drupal/helfi_azure_fs": "^2.0",
"drupal/helfi_drupal_tools": "dev-main",
"drupal/helfi_hakuvahti": "^1.0",
"drupal/helfi_navigation": "^2.0",
"drupal/helfi_platform_config": "^5.0",
"drupal/helfi_proxy": "^3.0",
Expand Down
394 changes: 311 additions & 83 deletions composer.lock

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions conf/cmi/block.block.hdbt_subtheme_hakuvahti.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
uuid: f73e721d-5865-48b3-a24a-051fa2f42961
langcode: en
status: true
dependencies:
module:
- helfi_kymp_content
- system
theme:
- hdbt_subtheme
id: hdbt_subtheme_hakuvahti
theme: hdbt_subtheme
region: content
weight: 5
provider: null
plugin: kymp_vehicle_removal
settings:
id: kymp_vehicle_removal
label: Hakuvahti
label_display: '0'
provider: helfi_kymp_content
visibility:
request_path:
id: request_path
negate: false
pages: "/pysakointi/ajoneuvojen-siirrot/ajoneuvojen-siirtokehotukset\r\n/parking/vehicle-removal/vehicle-removal-requests\r\n/parkering/forflyttning-av-fordon/flyttningsuppmaningar"
1 change: 1 addition & 0 deletions conf/cmi/core.extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ module:
helfi_ckeditor: 0
helfi_csp: 0
helfi_etusivu_entities: 0
helfi_hakuvahti: 0
helfi_hyte_search: 0
helfi_image_styles: 0
helfi_kymp_content: 0
Expand Down
9 changes: 9 additions & 0 deletions conf/cmi/helfi_hakuvahti.config.default.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
uuid: 10b0636e-5846-4ce6-a01f-ae4eaf8967be
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: VOToVi_aKYE5IrQ7kOYaB0Ki5hOC4kh2f_KF5FJqKnY
id: default
label: Default
site_id: 'kymp'
1 change: 1 addition & 0 deletions conf/cmi/helfi_hakuvahti.settings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
langcode: en
2 changes: 1 addition & 1 deletion conf/cmi/search_api.index.mobilenote_data.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ tracker_settings:
default:
indexing_order: fifo
options:
cron_limit: 20
cron_limit: 1
delete_on_fail: true
index_directly: false
track_changes_in_references: true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
vehicle-removal-search:
version: HELFI_DEPLOYMENT_IDENTIFIER
js: {}
# Theme will extend this library.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ use Drupal\node\NodeInterface;
/**
* Implements hook_theme().
*/
function helfi_kymp_content_theme() {
function helfi_kymp_content_theme(): array {
return [
'vehicle_removal' => [
'variables' => [],
],
'subdistricts_navigation' => [
'variables' => [
'navigation' => NULL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ services:

Drupal\helfi_kymp_content\StreetDataService: ~

Drupal\helfi_kymp_content\Paikkatieto\PaikkatietoClient: ~
Drupal\helfi_kymp_content\MobileNoteDataService: ~

162 changes: 26 additions & 136 deletions public/modules/custom/helfi_kymp_content/src/MobileNoteDataService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\TypedData\TypedDataManagerInterface;
use Drupal\helfi_kymp_content\Paikkatieto\PaikkatietoClient;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
use proj4php\Point;
Expand Down Expand Up @@ -35,24 +36,17 @@ class MobileNoteDataService {
*/
protected Proj $projTarget;

public const METHOD_BBOX = 'BBOX';
public const METHOD_POINT = 'POINT';

/**
* The street query mode to use.
*/
private const STREET_QUERY_MODE = self::METHOD_POINT;

/**
* Constructs a new MobileNoteDataService instance.
*/
public function __construct(
protected readonly ClientInterface $client,
protected readonly TypedDataManagerInterface $typedDataManager,
protected readonly TimeInterface $time,
protected readonly Settings $settings,
protected ClientInterface $client,
protected TypedDataManagerInterface $typedDataManager,
protected TimeInterface $time,
protected Settings $settings,
#[Autowire(service: 'logger.channel.helfi_kymp_content')]
protected readonly LoggerInterface $logger,
protected LoggerInterface $logger,
protected PaikkatietoClient $paikkatietoClient,
) {
// EPSG:3879 is Helsinki local CRS (ETRS-GK25FIN).
$this->proj4 = new Proj4php();
Expand Down Expand Up @@ -123,26 +117,29 @@ public function getMobileNoteData(): array {
* The items to fetch street names for.
*/
public function fetchNearbyStreets(array $items): void {
$apiSettings = $this->settings->get('helfi_kymp_mobilenote', []);
$apiKey = $apiSettings['address_api_key'] ?? NULL;

if (empty($apiKey)) {
$this->logger->warning('Paikkatietoapi: Missing API key.');
return;
}

foreach ($items as $item) {
$geo = $item->get('geometry')->getValue();

if ($geo) {
if (self::STREET_QUERY_MODE === self::METHOD_POINT) {
$result = $this->fetchStreetsByPoint($geo, $apiKey);
}
else {
$result = $this->fetchStreetsByBbox($geo, $apiKey);
}
$item->set('street_names', $result);
if (!$geo) {
continue;
}

if (empty($geo->coordinates)) {
continue;
}

if (!isset($geo->type) || $geo->type !== 'linestring') {
$this->logger->warning('Skipping item with unknown geometry type @type.', [
'@type' => $geo->type ?? '',
]);
}

// This can fail with an exception when the API is
// unable to handle too many requests. If that happens,
// the processing should fail and be re-tried automatically.
$result = $this->paikkatietoClient->fetchStreetsForLineString($geo->coordinates);

$item->set('street_names', $result);
}
}

Expand Down Expand Up @@ -303,111 +300,4 @@ protected function convertGeometry(array $geometry): object {
];
}

/**
* Fetches street names using the bounding box method.
*
* @param object $geometry
* The GeoJSON geometry object.
* @param string $apiKey
* The Address API key.
*
* @return array
* A list of unique street names found within the bounding box.
*/
protected function fetchStreetsByBbox(object $geometry, string $apiKey): array {
if (empty($geometry->coordinates)) {
return [];
}

// Calculate Bounding Box (minX, minY, maxX, maxY).
$lons = array_column($geometry->coordinates, 0);
$lats = array_column($geometry->coordinates, 1);

// Add buffer (approx 20m = 0.0002 deg) to ensure results for lines.
$buffer = 0.0002;
$minX = min($lons) - $buffer;
$maxX = max($lons) + $buffer;
$minY = min($lats) - $buffer;
$maxY = max($lats) + $buffer;

return $this->fetchStreetsFromApi([
'bbox' => implode(',', [$minX, $minY, $maxX, $maxY]),
'limit' => 20,
], $apiKey);
}

/**
* Fetches street names using the point-radius method.
*
* @param object $geometry
* The GeoJSON geometry object.
* @param string $apiKey
* The Address API key.
*
* @return array
* A list of unique street names found within radius.
*/
protected function fetchStreetsByPoint(object $geometry, string $apiKey): array {
if (empty($geometry->coordinates)) {
return [];
}

// Calculate Centroid.
$lons = array_column($geometry->coordinates, 0);
$lats = array_column($geometry->coordinates, 1);
$count = count($geometry->coordinates);

if ($count === 0) {
return [];
}

return $this->fetchStreetsFromApi([
'lat' => array_sum($lats) / $count,
'lon' => array_sum($lons) / $count,
'distance' => 20,
'limit' => 20,
], $apiKey);
}

/**
* Fetches street names from the Paikkatietohaku API.
*
* @param array $queryParams
* Query parameters for the API request.
* @param string $apiKey
* The Address API key.
*
* @return array
* A list of unique street names.
*/
protected function fetchStreetsFromApi(array $queryParams, string $apiKey): array {
try {
$response = $this->client->request('GET', 'https://paikkatietohaku.api.hel.fi/v1/address/', [
'headers' => ['Api-Key' => $apiKey],
'query' => $queryParams,
'timeout' => 60,
]);

$data = json_decode($response->getBody()->getContents(), TRUE);
$streets = [];

foreach ($data['results'] ?? [] as $result) {
if (!empty($result['street']['name']['fi'])) {
$streets[] = $result['street']['name']['fi'];
}
if (!empty($result['street']['name']['sv'])) {
$streets[] = $result['street']['name']['sv'];
}
}

return array_values(array_unique($streets));
}
catch (\Exception $e) {
$this->logger->error('Paikkatietoapi failed: @message', [
'@message' => $e->getMessage(),
]);
return [];
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Drupal\helfi_kymp_content\Paikkatieto;

/**
* Paikkatieto API exception.
*/
class Exception extends \Exception {
}
Loading