Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.31% covered (success)
92.31%
12 / 13
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
MapGeocodingService
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
4 / 4
5
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 searchAddress
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAddressFromCoordinates
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 geocodeAddressComponents
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Modules\Map\Application\Service;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Modules\Map\Domain\Model\GeoPoint;
12use App\Modules\Map\Domain\Repository\MapApiClientInterface;
13
14/**
15 * Map Geocoding Application Service.
16 *
17 * Coordinates address-to-coordinates and coordinates-to-address resolution.
18 *
19 * @package App\Modules\Map\Application\Service
20 */
21final class MapGeocodingService
22{
23    /**
24     * MapGeocodingService constructor.
25     *
26     * @param MapApiClientInterface $client Maps API client.
27     */
28    public function __construct(
29        private readonly MapApiClientInterface $client
30    ) {
31    }
32
33    /**
34     * Resolves a free-form address query into coordinate points.
35     *
36     * @param string $query Address query text.
37     * @param int    $limit Maximum candidates to return.
38     * @return array<int, GeoPoint> Found points.
39     */
40    public function searchAddress(string $query, int $limit = 5): array
41    {
42        return $this->client->geocode($query, $limit);
43    }
44
45    /**
46     * Resolves latitude and longitude into address structure.
47     *
48     * @param float $latitude  WGS-84 latitude.
49     * @param float $longitude WGS-84 longitude.
50     * @return GeoPoint|null Resolved point or null.
51     */
52    public function getAddressFromCoordinates(float $latitude, float $longitude): ?GeoPoint
53    {
54        return $this->client->reverseGeocode($latitude, $longitude);
55    }
56
57    /**
58     * Resolves coordinates for structured company/contact address fields.
59     *
60     * @param string $street         Street name and number.
61     * @param string $postalCode     Zip / postal code.
62     * @param string $city           City / town.
63     * @param string $country        Country.
64     * @return GeoPoint|null First matching point or null.
65     */
66    public function geocodeAddressComponents(
67        string $street,
68        string $postalCode,
69        string $city,
70        string $country = 'Polska'
71    ): ?GeoPoint {
72        $parts = array_filter(
73            [$street, $postalCode, $city, $country],
74            static fn(string $p): bool => trim($p) !== ''
75        );
76
77        if ($parts === []) {
78            return null;
79        }
80
81        $query = implode(', ', $parts);
82        $results = $this->client->geocode($query, 1);
83
84        return $results[0] ?? null;
85    }
86}