6 changed files with 465 additions and 51 deletions
@ -0,0 +1,183 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* RX2 - Main API to process in coming request for closest location. |
||||
|
* 2019-09-29 |
||||
|
* Rick Hays |
||||
|
* |
||||
|
*/ |
||||
|
|
||||
|
include_once 'assets/classes/geocode.php'; |
||||
|
|
||||
|
// See if we are in test mode ////////////////////////////////////////////////////////////////////////////////////// |
||||
|
$TEST = GetParam('T', 0); |
||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||||
|
|
||||
|
// Test Key before allowing access - No encryption, simple key test. |
||||
|
$key = strtoupper(GetParam('K')); |
||||
|
if ($key !== 'RLH4321') |
||||
|
{ |
||||
|
$result['status'] = 'ERROR'; |
||||
|
$result['code'] = '100'; |
||||
|
$result['description'] = 'Bad Key Code.'; |
||||
|
$jsonOut = json_encode($result); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
$request_method = strtoupper($_SERVER["REQUEST_METHOD"]); |
||||
|
$command = strtoupper(GetParam('C')); |
||||
|
$address = rawurldecode(GetParam('address')) . ''; |
||||
|
switch ($request_method) |
||||
|
{ |
||||
|
case 'GET': |
||||
|
switch ($command) |
||||
|
{ |
||||
|
case 'LL': |
||||
|
if ($address === '') |
||||
|
{ |
||||
|
$aOutput = array |
||||
|
( |
||||
|
'status' => 'ERROR', |
||||
|
'code' => '101', |
||||
|
'description' => 'No Address present.', |
||||
|
); |
||||
|
$jsonOut = json_encode($aOutput); |
||||
|
break; |
||||
|
} // if ($address === '') |
||||
|
$geo = new geocode(); |
||||
|
$latlon = $geo->getLatLong($address); |
||||
|
$jsonOut = json_encode($latlon); |
||||
|
$geo = NULL; |
||||
|
break; |
||||
|
case 'DIST': |
||||
|
if ($address === '') |
||||
|
{ |
||||
|
$aOutput = array |
||||
|
( |
||||
|
'status' => 'ERROR', |
||||
|
'code' => '101', |
||||
|
'description' => 'No Address present.', |
||||
|
); |
||||
|
$jsonOut = json_encode($aOutput); |
||||
|
break; |
||||
|
} // if ($address === '') |
||||
|
$geo = new geocode(); |
||||
|
$db = new PDO('sqlite:assets/db/RX.db'); |
||||
|
$latlon = $geo->getLatLong($address); |
||||
|
if ($latlon['status'] === 'OK') |
||||
|
{ |
||||
|
$shortest = 999999.99; // <-- Sets to a very high value to find shortest distance below. |
||||
|
$pharmacies = $db->query('SELECT rowid,* FROM pharmacies'); |
||||
|
$SKIP = 0; // Part of test mode to skip all but one record in DB |
||||
|
foreach ($pharmacies as $pharmacy) |
||||
|
{ |
||||
|
$destination = $pharmacy['Address'] . ' ' . $pharmacy['City'] . ' ' . $pharmacy['State'] . ' ' . $pharmacy['Zip']; |
||||
|
if ($SKIP === 0) $result = $geo->getDistance($address, $destination); |
||||
|
if ($TEST == 1) $SKIP = 1; |
||||
|
if ($result['status'] === 'OK') |
||||
|
{ |
||||
|
$distance = floatval(preg_replace('/[^0-9.]/', '', $result['distance'])); |
||||
|
if ($distance < $shortest) |
||||
|
{ |
||||
|
$aOutput = array |
||||
|
( |
||||
|
'pharmacy' => $pharmacy['Pharmacy'], |
||||
|
'address' => $pharmacy['Address'], |
||||
|
'city' => $pharmacy['City'], |
||||
|
'state' => $pharmacy['State'], |
||||
|
'zip' => $pharmacy['Zip'], |
||||
|
'latitude' => $pharmacy['Latitude'], |
||||
|
'longitude' => $pharmacy['Longitude'], |
||||
|
'home_lat' => $latlon['lat'], |
||||
|
'home_lon' => $latlon['lon'], |
||||
|
'status' => $result['status'], |
||||
|
'distance' => $result['distance'], |
||||
|
'duration' => $result['duration'], |
||||
|
); |
||||
|
$shortest = $distance; |
||||
|
} // if ($result['distance'] < $shortest) |
||||
|
} // if ($result['status'] === 'OK') |
||||
|
else |
||||
|
{ |
||||
|
$aOutput = array |
||||
|
( |
||||
|
'status' => 'ERROR', |
||||
|
'code' => '104', |
||||
|
'description' => "Problem returning distance between address and pharmacy.\nAddress: " . $address . "\nPharmacy( ROWID: " . $pharmacy['rowid'] . " Name: " . $pharmacy['Pharmacy'] . ') ', |
||||
|
); |
||||
|
$jsonOut = json_encode($aOutput); |
||||
|
break; |
||||
|
} //else ($result['status'] === 'OK') |
||||
|
} // foreach ($pharmacies as $pharmacy) |
||||
|
} // if ($latlon['status'] === 'OK') |
||||
|
else |
||||
|
{ |
||||
|
$aOutput = array |
||||
|
( |
||||
|
'status' => 'ERROR', |
||||
|
'code' => '103', |
||||
|
'description' => "Problem returning Lat / Lon.\nAddress: " . $address, |
||||
|
); |
||||
|
$jsonOut = json_encode($aOutput); |
||||
|
break; |
||||
|
|
||||
|
} // else ($latlon['status'] === 'OK') |
||||
|
$jsonOut = json_encode($aOutput); |
||||
|
$db = NULL; |
||||
|
$geo = NULL; |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
$aOutput = array |
||||
|
( |
||||
|
'status' => 'ERROR', |
||||
|
'code' => '102', |
||||
|
'description' => "Invalid Command sent - " . $command, |
||||
|
); |
||||
|
$jsonOut = json_encode($aOutput); |
||||
|
break; |
||||
|
|
||||
|
} // switch ($command) |
||||
|
break; |
||||
|
|
||||
|
// case 'POST': |
||||
|
// break; |
||||
|
// |
||||
|
// case 'PUT': |
||||
|
// break; |
||||
|
// |
||||
|
// case 'DELETE': |
||||
|
// break; |
||||
|
// |
||||
|
default: |
||||
|
// Invalid Request Method |
||||
|
header("HTTP/1.0 405 Method Not Allowed"); |
||||
|
exit; |
||||
|
|
||||
|
} // switch ($request_method) |
||||
|
} // else ($key !== 'RLH4321') |
||||
|
echo $jsonOut; |
||||
|
|
||||
|
// ##### END OF PROGRAM ################################################################################################ |
||||
|
|
||||
|
/** |
||||
|
* GetParam - Returns the GET or POST values, and allows for defaults if not present. |
||||
|
* @param $param_name |
||||
|
* @param null $default |
||||
|
* |
||||
|
* @return string|null |
||||
|
*/ |
||||
|
function GetParam($param_name, $default=NULL) |
||||
|
{ |
||||
|
global $_POST; |
||||
|
global $_GET; |
||||
|
$param_value = ""; |
||||
|
|
||||
|
if(isset($_POST[$param_name])) |
||||
|
$param_value = $_POST[$param_name]; |
||||
|
else if(isset($_GET[$param_name])) |
||||
|
$param_value = $_GET[$param_name]; |
||||
|
else if($param_value === '') |
||||
|
$param_value = $default; |
||||
|
|
||||
|
return $param_value; |
||||
|
} |
@ -0,0 +1,112 @@ |
|||||
|
<?php |
||||
|
/**************************************************** |
||||
|
* Geocode Class - Collection of geocoding Utilities |
||||
|
* |
||||
|
* Created By: Rick Hays |
||||
|
* Date: 2011-09-12 |
||||
|
* |
||||
|
* Revisions: |
||||
|
* 2011-09-12 RLH Added "straight_line_distance" |
||||
|
* 2011-09-12 RLH Added "getLatLong" |
||||
|
* 2019-09-28 RLH Added "getDistance" |
||||
|
* |
||||
|
*****************************************************/ |
||||
|
require_once 'key.php'; |
||||
|
|
||||
|
class geocode |
||||
|
{ |
||||
|
/******************************************************************************************************************* |
||||
|
* straight_line_distance - Returns Straight Line distance between two sets of (LAT/LONGS) |
||||
|
* |
||||
|
* @param float $lat1 - Latitude of Location #1 |
||||
|
* @param float $lon1 - Longitude of Location #1 |
||||
|
* @param float $lat2 - Latitude of Location #2 |
||||
|
* @param float $lon2 - Longitude of Location #2 |
||||
|
* @param string $unit - Unit of measure [DEFAULT = statute miles] ('K'=kilometers, 'N'=nautical miles) |
||||
|
* |
||||
|
* @return float - returns the distance in the desired unit of measure. |
||||
|
*/ |
||||
|
public function straight_line_distance($lat1, $lon1, $lat2, $lon2, $unit='') |
||||
|
{ |
||||
|
$theta = $lon1 - $lon2; |
||||
|
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); |
||||
|
$dist = acos($dist); |
||||
|
$dist = rad2deg($dist); |
||||
|
$miles = $dist * 60 * 1.1515; |
||||
|
$unit = strtoupper($unit); |
||||
|
if ($unit == "K") { return ($miles * 1.609344); } // Return in Kilometers |
||||
|
else if ($unit == "N") { return ($miles * 0.8684); } // Return in Nautical Miles |
||||
|
else { return $miles; } // Return in Miles |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************************************************* |
||||
|
* getLatLong - Converts a string with a street address into Lat/Long coordinates using a Google call. |
||||
|
* |
||||
|
* @param string $address - Text address to convert. |
||||
|
* |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function getLatLong($address) |
||||
|
{ |
||||
|
if (!is_string($address))die("All Addresses must be passed as a string"); |
||||
|
$_url = sprintf('https://maps.googleapis.com/maps/api/geocode/json?address=%s&'.API_KEY,rawurlencode($address)); |
||||
|
if($_result = file_get_contents($_url)) |
||||
|
{ |
||||
|
$decode = json_decode($_result,true); |
||||
|
$_coords['status'] = $decode['status']; |
||||
|
$_coords['lat'] = $decode['results'][0]['geometry']['location']['lat']; |
||||
|
$_coords['lon'] = $decode['results'][0]['geometry']['location']['lng']; |
||||
|
return $_coords; |
||||
|
}else die('Nothing was returned'); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/******************************************************************************************************************* |
||||
|
* @param $origin |
||||
|
* @param $destination |
||||
|
* @param string $mode (driving, walking, bicycling) |
||||
|
* @param string $units (metric, imperial) |
||||
|
* |
||||
|
* @return array |
||||
|
* @example - https://maps.googleapis.com/maps/api/distancematrix/json?'.$this->api_key.'&origins='.rawurlencode($origin).'&destinations='.rawurlencode($destination).'&mode=driving&units=imperial&sensor=false |
||||
|
* |
||||
|
*/ |
||||
|
public function getDistance($origin, $destination, $mode='driving', $unit='imperial') |
||||
|
{ |
||||
|
// Set defaults to test for |
||||
|
$modes = array('driving', 'walking', 'bicycling'); |
||||
|
$units = array('metric', 'imperial'); |
||||
|
|
||||
|
// Test that addresses are present |
||||
|
if (!is_string($origin) || !is_string($destination))die("All Addresses must be passed as a string"); |
||||
|
|
||||
|
// Test that Mode is present and of correct value |
||||
|
$mode = strtolower($mode); |
||||
|
if (!in_array($mode, $modes))die("Mode not correct"); |
||||
|
|
||||
|
// Test that Unit is present and of correct value |
||||
|
$unit = strtolower($unit); |
||||
|
if (!in_array($unit, $units))die("Unit not correct"); |
||||
|
|
||||
|
// Prep string for send ie(remove spaces and other objects) |
||||
|
$_origin = rawurlencode($origin); |
||||
|
$_destination = rawurlencode($destination); |
||||
|
$_mode = rawurlencode($mode); |
||||
|
$_unit = rawurlencode($unit); |
||||
|
|
||||
|
$_url = sprintf('https://maps.googleapis.com/maps/api/distancematrix/json?%s&origins=%s&destinations=%s&mode=%s&units=%s&sensor=false',API_KEY, $_origin, $_destination, $_mode, $_unit); |
||||
|
if($_result = file_get_contents($_url)) |
||||
|
{ |
||||
|
$decode = json_decode($_result,true); |
||||
|
$_dist['status'] = $decode['status']; |
||||
|
$_dist['distance'] = $decode['rows'][0]['elements'][0]['distance']['text']; |
||||
|
$_dist['duration'] = $decode['rows'][0]['elements'][0]['duration']['text']; |
||||
|
return $_dist; |
||||
|
}else die('Nothing was returned'); |
||||
|
} |
||||
|
|
||||
|
} // End Class GEOCODE |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
Can't render this file because it contains an unexpected character in line 25 and column 0.
|
Binary file not shown.
@ -0,0 +1,85 @@ |
|||||
|
function btnFind() |
||||
|
{ |
||||
|
// Reset Rows
|
||||
|
$("#alertBox").hide(); |
||||
|
$(".alert").html(""); |
||||
|
$('.alert').removeClass('alert-warning').removeClass('alert-danger').addClass('alert-warning'); |
||||
|
$("#spinnerBox").hide(); |
||||
|
$("#txtOutput").hide(); |
||||
|
|
||||
|
// Set Vars
|
||||
|
let txtAddress = $("#txtAddress").val() + ""; |
||||
|
// Quick test to make sure address was entered.
|
||||
|
if (txtAddress === "") |
||||
|
{ |
||||
|
$(".alert").html("You have to enter an address first."); |
||||
|
$("#alertBox").show(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// Show Spinner
|
||||
|
$("#spinnerBox").show(); |
||||
|
|
||||
|
// API - Call geocode API
|
||||
|
// K = (Required) Key, allows access to API
|
||||
|
// C = (Required) Command,
|
||||
|
// LL - Will return the Lat/Lon of a given address.
|
||||
|
// DIST - Will return the distance information.
|
||||
|
// T = (Optional) Test, Test Mode = 1 will only pull one record from the DB
|
||||
|
// ADDRESS = Address you want to return the Lat/Lon or Distance from.
|
||||
|
$.ajax( |
||||
|
{ |
||||
|
url : 'https://rhays.us/Examples/RX_API_Two/RX2.php', |
||||
|
type : 'GET', |
||||
|
dataType: 'json', |
||||
|
data : |
||||
|
{ |
||||
|
'K' : 'RLH4321', |
||||
|
'C' : 'DIST', |
||||
|
'T' : '1', |
||||
|
'address' : txtAddress, |
||||
|
}, |
||||
|
success : function(data) |
||||
|
{ |
||||
|
switch(data.status.toUpperCase()) |
||||
|
{ |
||||
|
case 'OK': |
||||
|
sOutput = '<p>The Pharmacy closest to the address location you entered is: </p>'; |
||||
|
sOutput = sOutput + 'Pharmacy: <b>' + data.pharmacy + '</b><br/>'; |
||||
|
sOutput = sOutput + 'Address: <b>' + data.address + '</b><br/>'; |
||||
|
sOutput = sOutput + 'City: <b>' + data.city + '</b><br/>'; |
||||
|
sOutput = sOutput + 'State: <b>' + data.state + '</b><br/>'; |
||||
|
sOutput = sOutput + 'Zip: <b>' + data.zip + '</b><br/><br/>'; |
||||
|
sOutput = sOutput + '<p>Approx. Drive time and distance:</p>'; |
||||
|
sOutput = sOutput + 'Distance: <b>' + data.distance + '</b><br/>'; |
||||
|
sOutput = sOutput + 'Duration: <b>' + data.duration + '</b><br/>'; |
||||
|
|
||||
|
$("#txtOutput").html(sOutput); |
||||
|
$("#spinnerBox").hide(); |
||||
|
$("#txtOutput").show(); |
||||
|
break; |
||||
|
case 'ERROR': |
||||
|
$("#spinnerBox").hide(); |
||||
|
$('.alert').removeClass('alert-warning').removeClass('alert-danger').addClass('alert-danger'); |
||||
|
$(".alert").html(JSON.stringify('Error code: ' + data.code + ' - ' + data.description)); |
||||
|
$("#alertBox").show(); |
||||
|
break; |
||||
|
} |
||||
|
}, |
||||
|
error : function(request,error) |
||||
|
{ |
||||
|
$("#spinnerBox").hide(); |
||||
|
$('.alert').removeClass('alert-warning').removeClass('alert-danger').addClass('alert-danger'); |
||||
|
$(".alert").html('SYSTEM.JS<br/> ' + JSON.stringify(request)); |
||||
|
$("#alertBox").show(); |
||||
|
return; |
||||
|
}, |
||||
|
// TODO: Hook to put in status codes
|
||||
|
// statusCode:
|
||||
|
// {
|
||||
|
// 404: function() {
|
||||
|
// alert( "page not found" );
|
||||
|
// }
|
||||
|
// },
|
||||
|
}); |
||||
|
} |
@ -1,55 +1,58 @@ |
|||||
<!DOCTYPE html> |
<!DOCTYPE html> |
||||
<html> |
<html lang="en"> |
||||
|
<head> |
||||
<head> |
|
||||
<meta charset="utf-8"> |
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no"> |
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no"> |
||||
<title>RX_API_Two</title> |
<title>RX_API_Two</title> |
||||
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css"> |
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css"> |
||||
<link rel="stylesheet" href="assets/css/styles.css"> |
<link rel="stylesheet" href="assets/css/styles.css"> |
||||
</head> |
<script src="assets/js/system.js"></script> |
||||
|
</head> |
||||
|
<body> |
||||
|
|
||||
<body> |
|
||||
<!-- Start: 2 Rows 1+3 Columns --> |
|
||||
<div></div> |
|
||||
<!-- End: 2 Rows 1+3 Columns --> |
|
||||
<!-- Start: 2 Rows 1+1 Columns --> |
|
||||
<div> |
|
||||
<div class="container"> |
<div class="container"> |
||||
|
<div><p> </p></div> |
||||
<div class="row"> |
<div class="row"> |
||||
<div class="col-md-12" style="background-color: #bca59e;"> |
<div class="col-md-12" style="background-color: #bca59e;"> |
||||
<h1 class="text-center">RX API Two</h1> |
<h1 class="text-center">RX API Two</h1> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
<div><p> </p></div> |
||||
<div class="row"> |
<div class="row"> |
||||
<div class="col-md-12 text-center align-self-center"><strong>Please enter your address to find the closest pharmacy near you.</strong></div> |
<div class="col-md-12 text-center align-self-center"><strong>Enter your address to find the closest pharmacy near you.</strong></div> |
||||
</div> |
|
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
<!-- End: 2 Rows 1+1 Columns --> |
|
||||
<!-- Start: 2 Rows 1+1 Columns --> |
|
||||
<div> |
|
||||
<div class="container"> |
<div class="container"> |
||||
<div class="row"> |
<div><p> </p></div> |
||||
<div class="col-md-12 text-center align-self-center m-auto"><input class="form-control-lg" type="text" maxlength="255" required="" placeholder="Type Address Here" autofocus="" style="width: 300px;"></div> |
<div id="alertBox" class="row collapse hide"> |
||||
|
<div class="col-md-12 text-center align-self-center"> |
||||
|
<div class="alert alert-warning" role="alert"> |
||||
|
<span><strong>Alert</strong> text.</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div><p> </p></div> |
||||
</div> |
</div> |
||||
<div class="row"> |
<div class="row"> |
||||
<div class="col-md-12 text-center align-self-center"><button class="btn btn-primary" type="button">Find Closest</button></div> |
<div class="col-md-12 text-center align-self-center m-auto"><input id="txtAddress" class="form-control-lg" type="text" maxlength="255" required="" placeholder="Type Address Here" autofocus="" style="width: 300px;"></div> |
||||
</div> |
</div> |
||||
|
<div><p> </p></div> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-12 text-center align-self-center"><button id="btnFind" class="btn btn-primary" type="button" onClick="btnFind()">Find Closest</button></div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
<!-- End: 2 Rows 1+1 Columns --> |
|
||||
<!-- Start: 1 Row 1 Column --> |
|
||||
<div> |
|
||||
<div class="container"> |
<div class="container"> |
||||
<div class="row"> |
<div><p> </p></div> |
||||
<div class="col-md-12"></div> |
<div id="spinnerBox" class="row collapse hide"> |
||||
|
<div class="col-md-12 text-center align-self-center"> |
||||
|
<span class="spinner-border spinner-border-lg" role="status"></span> |
||||
|
</div> |
||||
</div> |
</div> |
||||
|
<div id="txtOutput" class="row collapse hide" style="background-color: beige;"> |
||||
|
<div class="col-md-12"></div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
<!-- End: 1 Row 1 Column --> |
|
||||
<script src="assets/js/jquery.min.js"></script> |
<script src="assets/js/jquery.min.js"></script> |
||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script> |
<script src="assets/bootstrap/js/bootstrap.min.js"></script> |
||||
</body> |
</body> |
||||
|
|
||||
</html> |
</html> |
Loading…
Reference in new issue