Skip to content

Commit 7ddc810

Browse files
committed
added geocode service
1 parent 7b65e00 commit 7ddc810

File tree

3 files changed

+158
-0
lines changed

3 files changed

+158
-0
lines changed

app/base/tools/Utils/Geocoder.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
/**
4+
* SiteBase
5+
* PHP Version 8.3
6+
*
7+
* @category CMS / Framework
8+
* @package Degami\Sitebase
9+
* @author Mirko De Grandis <degami@github.com>
10+
* @license MIT https://opensource.org/licenses/mit-license.php
11+
* @link https://github.com/degami/sitebase
12+
*/
13+
14+
15+
namespace App\Base\Tools\Utils;
16+
17+
use App\Base\Abstracts\ContainerAwareObject;
18+
use Degami\Basics\Exceptions\BasicException;
19+
20+
class Geocoder extends ContainerAwareObject
21+
{
22+
/**
23+
* Geocoding using default provider (Nominatim)
24+
*
25+
* @param string $address
26+
* @param string $provider nominatim|google|opencage
27+
* @param array $options provider-specific options (apikey etc)
28+
* @return array|null ['lat' => float, 'lon' => float]
29+
* @throws BasicException
30+
*/
31+
public function geocode(string $address, string $provider = 'nominatim', array $options = []): ?array
32+
{
33+
return match ($provider) {
34+
'google' => $this->geocodeGoogle($address, $options['key'] ?? null),
35+
'opencage' => $this->geocodeOpenCage($address, $options['key'] ?? null),
36+
default => $this->geocodeNominatim($address),
37+
};
38+
}
39+
40+
41+
/**
42+
* ───────────────────────────────────────────────────────────
43+
* 1) NOMINATIM (OpenStreetMap) — NO API KEY
44+
* ───────────────────────────────────────────────────────────
45+
*/
46+
public function geocodeNominatim(string $address): ?array
47+
{
48+
$url = "https://nominatim.openstreetmap.org/search";
49+
50+
$reqOptions = [
51+
'query' => [
52+
'format' => 'json',
53+
'q' => $address,
54+
],
55+
'headers' => [
56+
'User-Agent' => 'Sitebase-Geocoder/1.0',
57+
],
58+
];
59+
60+
$response = $this->getUtils()->httpRequest($url, 'GET', $reqOptions);
61+
62+
if (!$response || !isset($response[0])) {
63+
return null;
64+
}
65+
66+
return [
67+
'lat' => (float) $response[0]->lat,
68+
'lon' => (float) $response[0]->lon,
69+
];
70+
}
71+
72+
73+
/**
74+
* ───────────────────────────────────────────────────────────
75+
* 2) GOOGLE GEOCODING API
76+
* Requires an API key
77+
* ───────────────────────────────────────────────────────────
78+
*/
79+
public function geocodeGoogle(string $address, ?string $apiKey): ?array
80+
{
81+
if (!$apiKey) {
82+
throw new BasicException("Google Geocoding API key missing");
83+
}
84+
85+
$url = "https://maps.googleapis.com/maps/api/geocode/json";
86+
87+
$reqOptions = [
88+
'query' => [
89+
'address' => $address,
90+
'key' => $apiKey,
91+
],
92+
];
93+
94+
$response = $this->getUtils()->httpRequest($url, 'GET', $reqOptions);
95+
96+
if (!$response || ($response->status ?? '') !== 'OK') {
97+
return null;
98+
}
99+
100+
$location = $response->results[0]->geometry->location;
101+
102+
return [
103+
'lat' => (float) $location->lat,
104+
'lon' => (float) $location->lng,
105+
];
106+
}
107+
108+
109+
/**
110+
* ───────────────────────────────────────────────────────────
111+
* 3) OPENCAGE GEOCODING
112+
* Requires an API Key
113+
* ───────────────────────────────────────────────────────────
114+
*/
115+
public function geocodeOpenCage(string $address, ?string $apiKey): ?array
116+
{
117+
if (!$apiKey) {
118+
throw new BasicException("OpenCage API key missing");
119+
}
120+
121+
$url = "https://api.opencagedata.com/geocode/v1/json";
122+
123+
$reqOptions = [
124+
'query' => [
125+
'q' => $address,
126+
'key' => $apiKey,
127+
],
128+
];
129+
130+
$response = $this->getUtils()->httpRequest($url, 'GET', $reqOptions);
131+
132+
if (!$response || empty($response->results)) {
133+
return null;
134+
}
135+
136+
$geometry = $response->results[0]->geometry;
137+
138+
return [
139+
'lat' => (float) $geometry->lat,
140+
'lon' => (float) $geometry->lng,
141+
];
142+
}
143+
}

app/base/traits/ContainerAwareTrait.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use App\Base\Tools\Utils\SiteData;
3030
use App\Base\Tools\Utils\Zip;
3131
use App\Base\Tools\Utils\GZip;
32+
use App\Base\Tools\Utils\Geocoder;
3233
use App\Base\Models\Website;
3334
use App\Base\Routers\Admin;
3435
use App\Base\Routing\RouteInfo;
@@ -531,4 +532,15 @@ public function getEnvironment(): EnvironmentManager
531532
{
532533
return $this->getService('environment');
533534
}
535+
536+
/**
537+
* gets geocoder
538+
*
539+
* @return Geocoder
540+
* @throws BasicException
541+
*/
542+
public function getGeocoder(): Geocoder
543+
{
544+
return $this->getService('geocoder');
545+
}
534546
}

config/di.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,7 @@
242242

243243
\App\Base\Environment\Manager::class => DI\autowire(\App\Base\Environment\Manager::class),
244244
'environment' => DI\get(\App\Base\Environment\Manager::class),
245+
246+
\App\Base\Tools\Utils\Geocoder::class => DI\autowire(\App\Base\Tools\Utils\Geocoder::class),
247+
'geocoder' => DI\get(\App\Base\Tools\Utils\Geocoder::class),
245248
];

0 commit comments

Comments
 (0)