Added Other AP
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
class AddressToArea
|
||||
{
|
||||
|
||||
public static function get($db, $address_id, $city, $country)
|
||||
{
|
||||
$message = null;
|
||||
$address_id = (int) $address_id;
|
||||
$city_id = (int) $city;
|
||||
$country_code = pg_escape_string($country);
|
||||
|
||||
$result_areas = [];
|
||||
$postal_areas = [];
|
||||
$radius_areas = [];
|
||||
$plygon_areas = [];
|
||||
|
||||
// Step 1: Load address
|
||||
$q = "SELECT * FROM address WHERE id=${address_id}";
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$address = pg_fetch_assoc($r);
|
||||
} else {
|
||||
return [null, "Address was not found"];
|
||||
}
|
||||
|
||||
// Step 2: Load areas for the city and country
|
||||
$q = "SELECT *
|
||||
FROM geofence_area
|
||||
WHERE "
|
||||
. (!empty($city_id) ? "city_id = ${city_id} AND" : '') .
|
||||
" country='${country_code}'";
|
||||
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
if ($f["type"] == "postal") {
|
||||
$postal_areas[] = $f;
|
||||
}
|
||||
if ($f["type"] == "radius") {
|
||||
$radius_areas[] = $f;
|
||||
}
|
||||
if ($f["type"] == "polygon") {
|
||||
$plygon_areas[] = $f;
|
||||
}
|
||||
$raw_areas[] = $f;
|
||||
}
|
||||
} else {
|
||||
return [null, pg_last_error()];
|
||||
}
|
||||
if (count($postal_areas) < 1 && count($radius_areas) < 1 && count($plygon_areas) < 1) {
|
||||
return [null, "No areas defined for the city/country"];
|
||||
}
|
||||
|
||||
$result_areas = AddressToArea::getAreasForAddress($db, $address, $postal_areas, $radius_areas, $plygon_areas);
|
||||
|
||||
return [$result_areas, $message];
|
||||
}
|
||||
|
||||
public static function getAreasForAddress($db, $address, $postal_areas, $radius_areas, $plygon_areas)
|
||||
{
|
||||
$result_areas = [];
|
||||
|
||||
// Process postal codes
|
||||
if (count($postal_areas) > 0) {
|
||||
foreach ($postal_areas as $area) {
|
||||
$boundaries = json_decode($area["boundaries"], true);
|
||||
$codes = $boundaries["postal_code"];
|
||||
// if postal is not empty
|
||||
if (!empty($address["postal"])) {
|
||||
foreach ($codes as $code) {
|
||||
if ($code != "" && $code == substr($address["postal"], 0, strlen($code))) {
|
||||
$result_areas[] = $area;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if postal is empty
|
||||
} else if ($address["latitude"] != 0 && $address["longitude"] != 0) {
|
||||
$radius = 10; // 10Km
|
||||
$postals = self::getPostalFromLatLng($db, $address["latitude"], $address["longitude"], $radius);
|
||||
|
||||
$flag = false;
|
||||
foreach ($postals as $postal) {
|
||||
if ($flag) {
|
||||
break;
|
||||
}
|
||||
foreach ($codes as $code) {
|
||||
if ($code != "" && $code == substr($postal, 0, strlen($code))) {
|
||||
$result_areas[] = $area;
|
||||
$flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process radius
|
||||
if ($address["latitude"] != 0 && $address["longitude"] != 0 && count($radius_areas) > 0) {
|
||||
foreach ($radius_areas as $area) {
|
||||
$boundaries = json_decode($area["boundaries"], true);
|
||||
if (isset($boundaries['radius'])) {
|
||||
$radius = $boundaries['radius'];
|
||||
|
||||
// query to check if belongs to a radius area
|
||||
$query = "SELECT ST_DWithin('" . $area['location'] . "', ST_SetSRID(ST_Point (" . $address["longitude"] . ", " . $address["latitude"] . "), 4326)::geography, ${radius}) as iscorrect";
|
||||
$data = pg_fetch_all(pg_query($db, $query));
|
||||
|
||||
if ($data[0]['iscorrect'] == "t") {
|
||||
$result_areas[] = $area;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process polygon
|
||||
if ($address["latitude"] != 0 && $address["longitude"] != 0 && count($plygon_areas) > 0) {
|
||||
foreach ($plygon_areas as $area) {
|
||||
$boundaries = json_decode($area["boundaries"], true);
|
||||
if (isset($boundaries['polygon'])) {
|
||||
$polygon = $boundaries['polygon'];
|
||||
$polygonCoords = [];
|
||||
foreach ($polygon as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
|
||||
// query to check if belongs to a polygon area
|
||||
$query = "SELECT ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), ST_SetSRID(ST_Point (" . $address["longitude"] . ", " . $address["latitude"] . "), 4326)) as iscorrect";
|
||||
$data = pg_fetch_all(pg_query($db, $query));
|
||||
|
||||
if ($data[0]['iscorrect'] == "t") {
|
||||
$result_areas[] = $area;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result_areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* get postal array from latitude, longitude
|
||||
*/
|
||||
public static function getPostalFromLatLng($db, float $latitude, float $longitude, int $distance_in_km): array
|
||||
{
|
||||
$earth_radius = 6371;
|
||||
$km_per_degree_lat = 111.2;
|
||||
$pi = 3.14 / 180;
|
||||
|
||||
$query = " SELECT postal FROM (
|
||||
SELECT
|
||||
CASE
|
||||
WHEN
|
||||
$latitude = address.latitude AND $longitude = address.longitude THEN 0
|
||||
ELSE
|
||||
$earth_radius * acos(
|
||||
cos( radians( {$latitude}) )
|
||||
* cos( radians( address.latitude ) )
|
||||
* cos( radians( address.longitude ) - radians( {$longitude} ) )
|
||||
+ sin( radians( {$latitude}) )
|
||||
* sin( radians( address.latitude ) ) )
|
||||
END AS distance
|
||||
, *
|
||||
FROM address
|
||||
WHERE
|
||||
address.postal IS NOT NULL
|
||||
AND address.latitude BETWEEN " . ($latitude - ($distance_in_km / $km_per_degree_lat)) .
|
||||
" AND " . ($latitude + ($distance_in_km / $km_per_degree_lat));
|
||||
|
||||
$delta = round($distance_in_km / ($km_per_degree_lat * COS(deg2rad($longitude))), 10);
|
||||
|
||||
// Bounding box for speed - latitude within range (longtitude to km not linear)
|
||||
if (cos($longitude * $pi) > 0) {
|
||||
|
||||
$from = $longitude - $delta;
|
||||
$to = $longitude + $delta;
|
||||
|
||||
$query .=
|
||||
" AND address.longitude" .
|
||||
" BETWEEN " . $from .
|
||||
" AND " . $to;
|
||||
|
||||
} else {
|
||||
|
||||
$from = $longitude + $delta;
|
||||
$to = $longitude - $delta;
|
||||
|
||||
$query .=
|
||||
" AND address.longitude" .
|
||||
" BETWEEN " . $from .
|
||||
" AND " . $to;
|
||||
|
||||
}
|
||||
|
||||
// distance limit for circle
|
||||
$query .= " ) address
|
||||
WHERE distance < " . $distance_in_km;
|
||||
|
||||
$rs = pg_query($db, $query);
|
||||
|
||||
if (!$rs) {
|
||||
throw new Exception(pg_last_error($db));
|
||||
}
|
||||
|
||||
return pg_fetch_all($rs) ? array_column(pg_fetch_all($rs), 'postal') : [];
|
||||
}
|
||||
}
|
||||
// vi:ts=2
|
||||
Reference in New Issue
Block a user