Add geocode endpoint
parent
7e0e8ac168
commit
c0c89ec8f7
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
use Geocoder\Query\GeocodeQuery;
|
||||
|
||||
$address = urldecode($VARS["address"]);
|
||||
$origaddress = $address;
|
||||
|
||||
$cacheresp = $memcache->get("gis.geocode." . sha1($origaddress));
|
||||
if ($cacheresp !== false && empty($VARS["nocache"])) {
|
||||
exitWithJson(json_decode($cacheresp, true));
|
||||
}
|
||||
|
||||
$geocoder = new \Geocoder\ProviderAggregator();
|
||||
$adapter = new \Http\Adapter\Guzzle7\Client();
|
||||
|
||||
$chain = new \Geocoder\Provider\Chain\Chain([
|
||||
new \Geocoder\Provider\Mapbox\Mapbox($adapter, env("mapbox_key")),
|
||||
new \Geocoder\Provider\MapQuest\MapQuest($adapter, env("mapquest_key"))
|
||||
]);
|
||||
|
||||
$geocoder->registerProvider($chain);
|
||||
|
||||
$query = GeocodeQuery::create($address)->withLimit(1);
|
||||
|
||||
if (isset($VARS["country"]) && preg_match("/^[A-Z]{2}$/", $VARS["country"])) {
|
||||
$query = $query->withData("country", $VARS["country"]);
|
||||
}
|
||||
|
||||
|
||||
$results = $geocoder->geocodeQuery($query);
|
||||
|
||||
if ($results->count() > 0) {
|
||||
$result = $results->first();
|
||||
} else {
|
||||
$output = [
|
||||
"status" => "ERROR",
|
||||
"message" => "Address not found.",
|
||||
"address" => [
|
||||
"original" => $origaddress,
|
||||
"street" => "",
|
||||
"postalCode" => ""
|
||||
],
|
||||
"coords" => [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"accuracy" => [
|
||||
"ok" => false
|
||||
],
|
||||
"provider" => ""
|
||||
];
|
||||
goto cacheout;
|
||||
}
|
||||
|
||||
$geolatitude = $result->getCoordinates()->getLatitude();
|
||||
$geolongitude = $result->getCoordinates()->getLongitude();
|
||||
|
||||
$accurate = !empty($result->getStreetNumber());
|
||||
|
||||
if ($accurate) {
|
||||
$address = implode(" ", [$result->getStreetNumber(), $result->getStreetName()]);
|
||||
} else {
|
||||
$address = $result->getStreetName();
|
||||
}
|
||||
|
||||
$output = [
|
||||
"status" => "OK",
|
||||
"address" => [
|
||||
"original" => $origaddress,
|
||||
"street" => ucwords(strtolower(StreetNormalizer::normalizeAddress($address))),
|
||||
"postalCode" => $result->getPostalCode()
|
||||
],
|
||||
"coords" => [
|
||||
$geolatitude,
|
||||
$geolongitude
|
||||
],
|
||||
"accuracy" => [
|
||||
"ok" => $accurate
|
||||
],
|
||||
"provider" => $result->getProvidedBy()
|
||||
];
|
||||
|
||||
cacheout:
|
||||
$memcache->set("gis.geocode." . sha1($origaddress), json_encode($output));
|
||||
exitWithJson($output);
|
@ -0,0 +1,471 @@
|
||||
<?php
|
||||
|
||||
class StreetNormalizer {
|
||||
/*
|
||||
* Machine-readable form of the chart at
|
||||
* https://pe.usps.com/text/pub28/28apc_002.htm
|
||||
* with loop->lp added
|
||||
*/
|
||||
|
||||
const SUFFIX_TABLE = [
|
||||
'ALLEE' => 'ALY',
|
||||
'ALLEY' => 'ALY',
|
||||
'ALLY' => 'ALY',
|
||||
'ANEX' => 'ANX',
|
||||
'ANNEX' => 'ANX',
|
||||
'ANNX' => 'ANX',
|
||||
'ARC ' => 'ARC',
|
||||
'ARCADE ' => 'ARC',
|
||||
'AV' => 'AVE',
|
||||
'AVEN' => 'AVE',
|
||||
'AVENU' => 'AVE',
|
||||
'AVENUE' => 'AVE',
|
||||
'AVN' => 'AVE',
|
||||
'AVNUE' => 'AVE',
|
||||
'BAYOO' => 'BYU',
|
||||
'BAYOU' => 'BYU',
|
||||
'BEACH' => 'BCH',
|
||||
'BEND' => 'BND',
|
||||
'BLUF' => 'BLF',
|
||||
'BLUFF' => 'BLF',
|
||||
'BLUFFS ' => 'BLFS',
|
||||
'BOT' => 'BTM',
|
||||
'BOTTM' => 'BTM',
|
||||
'BOTTOM' => 'BTM',
|
||||
'BOUL' => 'BLVD',
|
||||
'BOULEVARD ' => 'BLVD',
|
||||
'BOULV' => 'BLVD',
|
||||
'BRNCH' => 'BR',
|
||||
'BRANCH' => 'BR',
|
||||
'BRDGE' => 'BRG',
|
||||
'BRIDGE' => 'BRG',
|
||||
'BROOK' => 'BRK',
|
||||
'BROOKS ' => 'BRKS',
|
||||
'BURG' => 'BG',
|
||||
'BURGS' => 'BGS',
|
||||
'BYPA' => 'BYP',
|
||||
'BYPAS' => 'BYP',
|
||||
'BYPASS' => 'BYP',
|
||||
'BYPS' => 'BYP',
|
||||
'CAMP' => 'CP',
|
||||
'CMP' => 'CP',
|
||||
'CANYN' => 'CYN',
|
||||
'CANYON' => 'CYN',
|
||||
'CNYN' => 'CYN',
|
||||
'CAPE' => 'CPE',
|
||||
'CAUSEWAY' => 'CSWY',
|
||||
'CAUSWA' => 'CSWY',
|
||||
'CEN' => 'CTR',
|
||||
'CENT' => 'CTR',
|
||||
'CENTER' => 'CTR',
|
||||
'CENTR' => 'CTR',
|
||||
'CENTRE' => 'CTR',
|
||||
'CNTER' => 'CTR',
|
||||
'CNTR' => 'CTR',
|
||||
'CENTERS ' => 'CTRS',
|
||||
'CIRC' => 'CIR',
|
||||
'CIRCL' => 'CIR',
|
||||
'CIRCLE' => 'CIR',
|
||||
'CRCL' => 'CIR',
|
||||
'CRCLE' => 'CIR',
|
||||
'CIRCLES' => 'CIRS',
|
||||
'CLIFF' => 'CLF',
|
||||
'CLIFFS' => 'CLFS',
|
||||
'CLUB' => 'CLB',
|
||||
'COMMON' => 'CMN',
|
||||
'COMMONS' => 'CMNS',
|
||||
'CORNER' => 'COR',
|
||||
'CORNERS' => 'CORS',
|
||||
'COURSE' => 'CRSE',
|
||||
'COURT' => 'CT',
|
||||
'COURTS' => 'CTS',
|
||||
'COVE' => 'CV',
|
||||
'COVES' => 'CVS',
|
||||
'CREEK' => 'CRK',
|
||||
'CRESCENT' => 'CRES',
|
||||
'CRSENT' => 'CRES',
|
||||
'CRSNT' => 'CRES',
|
||||
'CREST' => 'CRST',
|
||||
'CROSSING ' => 'XING',
|
||||
'CRSSNG ' => 'XING',
|
||||
'XING ' => 'XING',
|
||||
'CROSSROAD' => 'XRD',
|
||||
'CROSSROADS' => 'XRDS',
|
||||
'CURVE ' => 'CURV',
|
||||
'DALE ' => 'DL',
|
||||
'DL ' => 'DL',
|
||||
'DAM ' => 'DM',
|
||||
'DM ' => 'DM',
|
||||
'DIV' => 'DV',
|
||||
'DIVIDE' => 'DV',
|
||||
'DVD' => 'DV',
|
||||
'DRIV' => 'DR',
|
||||
'DRIVE' => 'DR',
|
||||
'DRV' => 'DR',
|
||||
'DRIVES' => 'DRS',
|
||||
'ESTATE' => 'EST',
|
||||
'ESTATES' => 'ESTS',
|
||||
'EXP' => 'EXPY',
|
||||
'EXPR' => 'EXPY',
|
||||
'EXPRESS' => 'EXPY',
|
||||
'EXPRESSWAY' => 'EXPY',
|
||||
'EXPW' => 'EXPY',
|
||||
'EXTENSION' => 'EXT',
|
||||
'EXTN' => 'EXT',
|
||||
'EXTNSN' => 'EXT',
|
||||
'FALLS' => 'FLS',
|
||||
'FERRY' => 'FRY',
|
||||
'FRRY' => 'FRY',
|
||||
'FIELD' => 'FLD',
|
||||
'FIELDS' => 'FLDS',
|
||||
'FLAT' => 'FLT',
|
||||
'FLATS' => 'FLTS',
|
||||
'FORD' => 'FRD',
|
||||
'FORDS' => 'FRDS',
|
||||
'FOREST' => 'FRST',
|
||||
'FORESTS' => 'FRST',
|
||||
'FORG' => 'FRG',
|
||||
'FORGE' => 'FRG',
|
||||
'FORGES' => 'FRGS',
|
||||
'FORK' => 'FRK',
|
||||
'FORKS' => 'FRKS',
|
||||
'FORT' => 'FT',
|
||||
'FRT' => 'FT',
|
||||
'FREEWAY' => 'FWY',
|
||||
'FREEWY' => 'FWY',
|
||||
'FRWAY' => 'FWY',
|
||||
'FRWY' => 'FWY',
|
||||
'GARDEN' => 'GDN',
|
||||
'GARDN' => 'GDN',
|
||||
'GRDEN' => 'GDN',
|
||||
'GRDN' => 'GDN',
|
||||
'GARDENS' => 'GDNS',
|
||||
'GRDNS' => 'GDNS',
|
||||
'GATEWAY' => 'GTWY',
|
||||
'GATEWY' => 'GTWY',
|
||||
'GATWAY' => 'GTWY',
|
||||
'GTWAY' => 'GTWY',
|
||||
'GLEN' => 'GLN',
|
||||
'GLENS' => 'GLNS',
|
||||
'GREEN' => 'GRN',
|
||||
'GREENS' => 'GRNS',
|
||||
'GROV' => 'GRV',
|
||||
'GROVE' => 'GRV',
|
||||
'GROVES' => 'GRVS',
|
||||
'HARB' => 'HBR',
|
||||
'HARBOR' => 'HBR',
|
||||
'HARBR' => 'HBR',
|
||||
'HRBOR' => 'HBR',
|
||||
'HARBORS' => 'HBRS',
|
||||
'HAVEN' => 'HVN',
|
||||
'HT' => 'HTS',
|
||||
'HIGHWAY' => 'HWY',
|
||||
'HIGHWY' => 'HWY',
|
||||
'HIWAY' => 'HWY',
|
||||
'HIWY' => 'HWY',
|
||||
'HWAY' => 'HWY',
|
||||
'HILL' => 'HL',
|
||||
'HILLS' => 'HLS',
|
||||
'HLLW' => 'HOLW',
|
||||
'HOLLOW' => 'HOLW',
|
||||
'HOLLOWS' => 'HOLW',
|
||||
'HOLWS' => 'HOLW',
|
||||
'ISLAND' => 'IS',
|
||||
'ISLND' => 'IS',
|
||||
'ISLANDS' => 'ISS',
|
||||
'ISLNDS' => 'ISS',
|
||||
'ISLES' => 'ISLE',
|
||||
'JCTION' => 'JCT',
|
||||
'JCTN' => 'JCT',
|
||||
'JUNCTION' => 'JCT',
|
||||
'JUNCTN' => 'JCT',
|
||||
'JUNCTON' => 'JCT',
|
||||
'JCTNS' => 'JCTS',
|
||||
'JUNCTIONS' => 'JCTS',
|
||||
'KEY' => 'KY',
|
||||
'KEYS' => 'KYS',
|
||||
'KNL' => 'KNL',
|
||||
'KNOL' => 'KNL',
|
||||
'KNOLL' => 'KNL',
|
||||
'KNOLLS' => 'KNLS',
|
||||
'LAKE' => 'LK',
|
||||
'LAKES' => 'LKS',
|
||||
'LANDING' => 'LNDG',
|
||||
'LNDNG' => 'LNDG',
|
||||
'LANE' => 'LN',
|
||||
'LIGHT' => 'LGT',
|
||||
'LIGHTS' => 'LGTS',
|
||||
'LOAF' => 'LF',
|
||||
'LOCK' => 'LCK',
|
||||
'LOCKS' => 'LCKS',
|
||||
'LDGE' => 'LDG',
|
||||
'LODG' => 'LDG',
|
||||
'LODGE' => 'LDG',
|
||||
'MANOR' => 'MNR',
|
||||
'MANORS' => 'MNRS',
|
||||
'MEADOW' => 'MDW',
|
||||
'MDW' => 'MDWS',
|
||||
'MEADOWS' => 'MDWS',
|
||||
'MEDOWS' => 'MDWS',
|
||||
'MILL' => 'ML',
|
||||
'MILLS' => 'MLS',
|
||||
'MISSN' => 'MSN',
|
||||
'MSSN' => 'MSN',
|
||||
'MOTORWAY' => 'MTWY',
|
||||
'MNT' => 'MT',
|
||||
'MOUNT' => 'MT',
|
||||
'MNTAIN' => 'MTN',
|
||||
'MNTN' => 'MTN',
|
||||
'MOUNTAIN' => 'MTN',
|
||||
'MOUNTIN' => 'MTN',
|
||||
'MTIN' => 'MTN',
|
||||
'MNTNS' => 'MTNS',
|
||||
'MOUNTAINS' => 'MTNS',
|
||||
'NECK' => 'NCK',
|
||||
'ORCHARD' => 'ORCH',
|
||||
'ORCHRD' => 'ORCH',
|
||||
'OVL' => 'OVAL',
|
||||
'OVERPASS' => 'OPAS',
|
||||
'PRK' => 'PARK',
|
||||
'PARKS' => 'PARK',
|
||||
'PARKWAY' => 'PKWY',
|
||||
'PARKWY' => 'PKWY',
|
||||
'PKWAY' => 'PKWY',
|
||||
'PKY' => 'PKWY',
|
||||
'PARKWAYS' => 'PKWY',
|
||||
'PKWYS' => 'PKWY',
|
||||
'PASSAGE' => 'PSGE',
|
||||
'PATHS' => 'PATH',
|
||||
'PIKES' => 'PIKE',
|
||||
'PINE' => 'PNE',
|
||||
'PINES' => 'PNES',
|
||||
'PLAIN' => 'PLN',
|
||||
'PLAINS' => 'PLNS',
|
||||
'PLAZA' => 'PLZ',
|
||||
'PLZA' => 'PLZ',
|
||||
'POINT' => 'PT',
|
||||
'POINTS' => 'PTS',
|
||||
'PORT' => 'PRT',
|
||||
'PORTS' => 'PRTS',
|
||||
'PRAIRIE' => 'PR',
|
||||
'PRR' => 'PR',
|
||||
'RAD' => 'RADL',
|
||||
'RADIAL' => 'RADL',
|
||||
'RADIEL' => 'RADL',
|
||||
'RANCH' => 'RNCH',
|
||||
'RANCHES' => 'RNCH',
|
||||
'RNCHS' => 'RNCH',
|
||||
'RAPID' => 'RPD',
|
||||
'RAPIDS' => 'RPDS',
|
||||
'REST' => 'RST',
|
||||
'RDGE' => 'RDG',
|
||||
'RIDGE' => 'RDG',
|
||||
'RIDGES' => 'RDGS',
|
||||
'RIVER' => 'RIV',
|
||||
'RVR' => 'RIV',
|
||||
'RIVR' => 'RIV',
|
||||
'ROAD' => 'RD',
|
||||
'ROADS' => 'RDS',
|
||||
'ROUTE' => 'RTE',
|
||||
'SHOAL' => 'SHL',
|
||||
'SHOALS' => 'SHLS',
|
||||
'SHOAR' => 'SHR',
|
||||
'SHORE' => 'SHR',
|
||||
'SHOARS' => 'SHRS',
|
||||
'SHORES' => 'SHRS',
|
||||
'SKYWAY' => 'SKWY',
|
||||
'SPNG' => 'SPG',
|
||||
'SPRING' => 'SPG',
|
||||
'SPRNG' => 'SPG',
|
||||
'SPNGS' => 'SPGS',
|
||||
'SPRINGS' => 'SPGS',
|
||||
'SPRNGS' => 'SPGS',
|
||||
'SPURS' => 'SPUR',
|
||||
'SQR' => 'SQ',
|
||||
'SQRE' => 'SQ',
|
||||
'SQU' => 'SQ',
|
||||
'SQUARE' => 'SQ',
|
||||
'SQRS' => 'SQS',
|
||||
'SQUARES' => 'SQS',
|
||||
'STATION' => 'STA',
|
||||
'STATN' => 'STA',
|
||||
'STN' => 'STA',
|
||||
'STRAV' => 'STRA',
|
||||
'STRAVEN' => 'STRA',
|
||||
'STRAVENUE' => 'STRA',
|
||||
'STRAVN' => 'STRA',
|
||||
'STRVN' => 'STRA',
|
||||
'STRVNUE' => 'STRA',
|
||||
'STREAM' => 'STRM',
|
||||
'STREME' => 'STRM',
|
||||
'STREET' => 'ST',
|
||||
'STRT' => 'ST',
|
||||
'STR' => 'ST',
|
||||
'STREETS' => 'STS',
|
||||
'SUMIT' => 'SMT',
|
||||
'SUMITT' => 'SMT',
|
||||
'SUMMIT' => 'SMT',
|
||||
'TERR' => 'TER',
|
||||
'TERRACE' => 'TER',
|
||||
'THROUGHWAY' => 'TRWY',
|
||||
'TRACE' => 'TRCE',
|
||||
'TRACES' => 'TRCE',
|
||||
'TRACK' => 'TRAK',
|
||||
'TRACKS' => 'TRAK',
|
||||
'TRK' => 'TRAK',
|
||||
'TRKS' => 'TRAK',
|
||||
'TRAFFICWAY' => 'TRFY',
|
||||
'TRAIL' => 'TRL',
|
||||
'TRAILS' => 'TRL',
|
||||
'TRLS' => 'TRL',
|
||||
'TRAILER' => 'TRLR',
|
||||
'TRLRS' => 'TRLR',
|
||||
'TUNEL' => 'TUNL',
|
||||
'TUNLS' => 'TUNL',
|
||||
'TUNNEL' => 'TUNL',
|
||||
'TUNNELS' => 'TUNL',
|
||||
'TUNNL' => 'TUNL',
|
||||
'TRNPK' => 'TPKE',
|
||||
'TURNPIKE' => 'TPKE',
|
||||
'TURNPK' => 'TPKE',
|
||||
'UNDERPASS' => 'UPAS',
|
||||
'UNION' => 'UN',
|
||||
'UNIONS' => 'UNS',
|
||||
'VALLEY' => 'VLY',
|
||||
'VALLY' => 'VLY',
|
||||
'VLLY' => 'VLY',
|
||||
'VALLEYS' => 'VLYS',
|
||||
'VDCT' => 'VIA',
|
||||
'VIADCT' => 'VIA',
|
||||
'VIADUCT' => 'VIA',
|
||||
'VIEW' => 'VW',
|
||||
'VIEWS' => 'VWS',
|
||||
'VILL' => 'VLG',
|
||||
'VILLAG' => 'VLG',
|
||||
'VILLAGE' => 'VLG',
|
||||
'VILLG' => 'VLG',
|
||||
'VILLIAGE' => 'VLG',
|
||||
'VILLAGES' => 'VLGS',
|
||||
'VILLE' => 'VL',
|
||||
'VIST' => 'VIS',
|
||||
'VISTA' => 'VIS',
|
||||
'VST' => 'VIS',
|
||||
'VSTA' => 'VIS',
|
||||
'WALKS' => 'WALK',
|
||||
'WY' => 'WAY',
|
||||
'WELL' => 'WL',
|
||||
'WELLS' => 'WLS'
|
||||
];
|
||||
const CARDINAL_TABLE = [
|
||||
"NORTH" => "N",
|
||||
"SOUTH" => "S",
|
||||
"EAST" => "E",
|
||||
"WEST" => "W",
|
||||
"NORTHWEST" => "NW",
|
||||
"SOUTHWEST" => "SW",
|
||||
"NORTHEAST" => "NE",
|
||||
"SOUTHEAST" => "SE"
|
||||
];
|
||||
|
||||
/**
|
||||
* Normalize a street name (ex. Street Road)
|
||||
* @param string $street
|
||||
* @param bool $python Set to false to use built-in less-accurate code,
|
||||
* or true to use normalize.py and https://github.com/mcmire/address_standardization
|
||||
* @return string
|
||||
*/
|
||||
public static function normalizeStreet(string $street, bool $python = true): string {
|
||||
// Give the script a dummy house number so it doesn't get lost
|
||||
$filler_address = "10000001 ";
|
||||
|
||||
return str_replace($filler_address, "", static::normalizeAddress($filler_address . $street));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize an address line (ex. 1234 street road)
|
||||
* @param string $address
|
||||
* @param bool $python Set to false to use built-in less-accurate code,
|
||||
* or true to use normalize.py and https://github.com/mcmire/address_standardization
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function normalizeAddress(string $address, bool $python = true): string {
|
||||
global $SETTINGS;
|
||||
try {
|
||||
if (empty($SETTINGS["normalize_python_script"]) || !file_exists($SETTINGS["normalize_python_script"])) {
|
||||
throw new Exception("failing back to builtin: python script missing");
|
||||
}
|
||||
if (!$python) {
|
||||
throw new Exception("failing back to builtin due to user request");
|
||||
}
|
||||
|
||||
$escaped = escapeshellarg($address);
|
||||
|
||||
$json = shell_exec($SETTINGS["normalize_python_script"] . " " . $escaped);
|
||||
|
||||
$address = json_decode($json, true);
|
||||
if (empty($address)) {
|
||||
throw new Exception("failing back to builtin due to JSON error");
|
||||
}
|
||||
|
||||
$address = $address["address_line_1"];
|
||||
return $address;
|
||||
} catch (Exception $ex) {
|
||||
$address = strtoupper(trim($address));
|
||||
|
||||
$address = static::normalizeSuffix($address);
|
||||
$address = static::normalizeCardinals($address);
|
||||
|
||||
return $address;
|
||||
}
|
||||
}
|
||||
|
||||
private static function findReplace(string $str, array $lookuptable) {
|
||||
foreach ($lookuptable as $find => $replace) {
|
||||
if ($str == $find) {
|
||||
$str = $replace;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
private static function findReplaceAll(string $str, array $lookuptable, string $seperator = " ") {
|
||||
$words = explode($seperator, $str);
|
||||
for ($i = 0; $i < count($words); $i++) {
|
||||
$words[$i] = static::findReplace($words[$i], $lookuptable);
|
||||
}
|
||||
|
||||
return implode($seperator, $words);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace cardinal/compass directions with abbreviations
|
||||
* @param string $street
|
||||
* @return string
|
||||
*/
|
||||
public static function normalizeCardinals(string $street): string {
|
||||
$street = strtoupper(trim($street));
|
||||
|
||||
return static::findReplaceAll($street, static::CARDINAL_TABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the street suffix with the standard abbreviation.
|
||||
* @param string $street
|
||||
* @return string
|
||||
*/
|
||||
public static function normalizeSuffix(string $street): string {
|
||||
$street = strtoupper(trim($street));
|
||||
|
||||
$parts = explode(" ", $street);
|
||||
|
||||
$suffix = static::findReplace(end($parts), static::SUFFIX_TABLE);
|
||||
|
||||
$parts[count($parts) - 1] = $suffix;
|
||||
|
||||
return implode(" ", $parts);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
function parse_citystatezip($citystatezip) {
|
||||
$citystatezip = strtoupper(trim($citystatezip));
|
||||
|
||||
$fullregex = "/^(.+), ?(.+)[,| |, ]([0-9]{5})(-[0-9]{4})?$/";
|
||||
$citystateregex = "/^(\w+)[,\s]+([A-Z]{2,})+$/";
|
||||
|
||||
if (!preg_match($fullregex, $citystatezip, $matches)) {
|
||||
if (!preg_match($citystateregex, $citystatezip, $matches)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
"city" => $matches[1],
|
||||
"state" => $matches[2],
|
||||
"zip" => isset($matches[3]) ? $matches[3] : null
|
||||
];
|
||||
}
|
||||
|
||||
function parse_citystate($citystate) {
|
||||
$citystate = strtoupper(trim($citystate));
|
||||
|
||||
$regex = "/^(\w+)[,\s]+([A-Z]{2,})+$/";
|
||||
|
||||
if (!preg_match($regex, $citystate, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
"city" => $matches[1],
|
||||
"state" => $matches[2]
|
||||
];
|
||||
}
|
||||
|
||||
function geocode_returnresult($query) {
|
||||
global $SETTINGS, $database;
|
||||
|
||||
$geocoder = new \Geocoder\ProviderAggregator();
|
||||
$adapter = new \Http\Adapter\Guzzle6\Client();
|
||||
|
||||
$chain = new \Geocoder\Provider\Chain\Chain([
|
||||
new \Geocoder\Provider\LocalDatabase\LocalDatabase($database),
|
||||
new \Geocoder\Provider\Mapbox\Mapbox($adapter, $SETTINGS["mapbox_key"]),
|
||||
new \Geocoder\Provider\MapQuest\MapQuest($adapter, $SETTINGS["mapquest_key"])
|
||||
]);
|
||||
|
||||
$geocoder->registerProvider($chain);
|
||||
|
||||
$results = $geocoder->geocodeQuery($query);
|
||||
|
||||
|
||||
if ($results->count() > 0) {
|
||||
$result = $results->first();
|
||||
} else {
|
||||
header("Content-Type: application/json");
|
||||
return [
|
||||
"status" => "ERROR",
|
||||
"message" => "That address doesn't seem to exist. If this is an error, please send the full address (including city, state, and ZIP) to support@netsyms.com.",
|
||||
"address" => [
|
||||
"street" => "",
|
||||
"postalCode" => ""
|
||||
],
|
||||
"coords" => [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"accuracy" => [
|
||||
"ok" => false
|
||||
],
|
||||
"provider" => ""
|
||||
];
|
||||
}
|
||||
|
||||
$geolatitude = $result->getCoordinates()->getLatitude();
|
||||
$geolongitude = $result->getCoordinates()->getLongitude();
|
||||
|
||||
$accurate = !empty($result->getStreetNumber());
|
||||
|
||||
if ($accurate) {
|
||||
$address = implode(" ", [$result->getStreetNumber(), $result->getStreetName()]);
|
||||
} else {
|
||||
$address = $result->getStreetName();
|
||||
}
|
||||
|
||||
|
||||
return [
|
||||
"status" => "OK",
|
||||
"address" => [
|
||||
"street" => ucwords(strtolower(StreetNormalizer::normalizeAddress($address))),
|
||||
"postalCode" => $result->getPostalCode()
|
||||
],
|
||||
"coords" => [
|
||||
$geolatitude,
|
||||
$geolongitude
|
||||
],
|
||||
"accuracy" => [
|
||||
"ok" => $accurate
|
||||
],
|
||||
"provider" => $result->getProvidedBy()
|
||||
];
|
||||
}
|
||||
|
||||
function geocode_addrstring($address) {
|
||||
$query = Geocoder\Query\GeocodeQuery::create($address)->withLimit(1);
|
||||
return geocode_returnresult($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Geocode an address.
|
||||
* @global type $SETTINGS
|
||||
* @param type $number
|
||||
* @param type $street
|
||||
* @param type $unit
|
||||
* @param type $city
|
||||
* @param type $state
|
||||
* @param type $zip
|
||||
* @param type $country
|
||||
* @param type $type
|
||||
* @return type
|
||||
*/
|
||||
function geocode($number, $street, $unit = null, $city, $state, $zip = null, $country = null, $type = null) {
|
||||
$address = "$number $street $city $state";
|
||||
$origaddress = "$number $street";
|
||||
|
||||
$query = Geocoder\Query\GeocodeQuery::create($address)
|
||||
->withLimit(1)
|
||||
->withData("number", $number)
|
||||
->withData("street", $street)
|
||||
->withData("city", $city)
|
||||
->withData("state", $state);
|
||||
if (!is_null($zip) && preg_match("/^([0-9]{5})/", $zip, $matches)) {
|
||||
if (count($matches) > 0) {
|
||||
$query = $query->withData("zip", $matches[0]);
|
||||
}
|
||||
}
|
||||
if (!is_null($unit) && !empty($unit)) {
|
||||
$query = $query->withData("unit", $unit);
|
||||
}
|
||||
|
||||
if (!is_null($type) && count(array_diff(explode("|", $type), $SETTINGS["address_types"])) == 0) {
|
||||
$query = $query->withData("locationtype", $type);
|
||||
}
|
||||
|
||||
if (!is_null($country) && preg_match("/^[A-Z]{2}$/", $country)) {
|
||||
$query = $query->withData("country", $country);
|
||||
}
|
||||
|
||||
return geocode_returnresult($query);
|
||||
}
|
Loading…
Reference in New Issue