Browse Source

add core files

geocoding and timezone works
main
Aaron Parecki 8 years ago
parent
commit
f102a75b88
14 changed files with 23076 additions and 1 deletions
  1. +2
    -1
      .gitignore
  2. +61
    -0
      controllers/geocode.php
  3. +10
    -0
      controllers/main.php
  4. +33
    -0
      controllers/timezone.php
  5. +0
    -0
      lib/config.template.php
  6. +25
    -0
      lib/helpers.php
  7. +109
    -0
      p3k/Geocoder.php
  8. +22688
    -0
      p3k/Timezone.php
  9. +41
    -0
      p3k/geocode/Result.php
  10. +33
    -0
      p3k/timezone/Result.php
  11. +15
    -0
      public/.htaccess
  12. +11
    -0
      public/index.php
  13. +29
    -0
      views/index.php
  14. +19
    -0
      views/layout.php

+ 2
- 1
.gitignore View File

@ -1,2 +1,3 @@
.DS_Store
vendor/
vendor/
lib/config.php

+ 61
- 0
controllers/geocode.php View File

@ -0,0 +1,61 @@
<?php
$app->get('/api/geocode', function() use($app) {
$params = $app->request()->params();
if(
(k($params, 'latitude') !== null && k($params, 'longitude') !== null)
|| k($params, 'input') !== null
) {
$response = [
'latitude' => null,
'longitude' => null,
'locality' => null,
'region' => null,
'country' => null,
'best_name' => null,
'full_name' => null,
'timezone' => null,
'offset' => null,
'seconds' => null,
'localtime' => null,
];
if(k($params, 'input')) {
$adr = p3k\Geocoder::geocode($params['input']);
} else {
$lat = (float)$params['latitude'];
$lng = (float)$params['longitude'];
$response['latitude'] = $lat;
$response['longitude'] = $lng;
$adr = p3k\Geocoder::adrFromLocation($lat, $lng);
}
if($adr) {
$response['latitude'] = $adr->latitude;
$response['longitude'] = $adr->longitude;
$response['locality'] = $adr->localityName;
$response['region'] = $adr->regionName;
$response['country'] = $adr->countryName;
$response['best_name'] = $adr->bestName;
$response['full_name'] = $adr->fullName;
}
$timezone = p3k\Timezone::timezone_for_location($response['latitude'], $response['longitude']);
if($timezone) {
$response['timezone'] = $timezone->name;
$response['offset'] = $timezone->offset;
$response['seconds'] = $timezone->seconds;
$response['localtime'] = $timezone->localtime;
}
json_response($app, $response);
} else {
json_response($app, [
'error' => 'invalid_request',
'error_description' => 'Request was missing parameters'
], 400);
}
});

+ 10
- 0
controllers/main.php View File

@ -0,0 +1,10 @@
<?php
use \Slim\Savant;
$app->get('/', function() use($app) {
return Savant\render('index');
});
$app->get('/map', function() use($app) {
return Savant\render('map');
});

+ 33
- 0
controllers/timezone.php View File

@ -0,0 +1,33 @@
<?php
$app->get('/api/timezone', function() use($app) {
$params = $app->request()->params();
if(k($params, 'latitude') !== null && k($params, 'longitude') !== null) {
$lat = (float)$params['latitude'];
$lng = (float)$params['longitude'];
$timezone = \p3k\Timezone::timezone_for_location($lat, $lng);
if($timezone) {
json_response($app, [
'timezone' => $timezone->name,
'offset' => $timezone->offset,
'seconds' => $timezone->seconds,
'localtime' => $timezone->localtime
]);
} else {
json_response($app, [
'error' => 'not_found',
'error_description' => 'No timezone was found for the requested location'
]);
}
} else {
json_response($app, [
'error' => 'invalid_request',
'error_description' => 'Request was missing parameters'
], 400);
}
});

+ 0
- 0
lib/config.template.php View File


+ 25
- 0
lib/helpers.php View File

@ -0,0 +1,25 @@
<?php
function json_response(&$app, $response, $code=200) {
$app->response()->status($code);
$app->response()['Content-Type'] = 'application/json';
$app->response()->body(json_encode($response));
}
function k($a, $k, $default=null) {
if(is_array($k)) {
$result = true;
foreach($k as $key) {
$result = $result && array_key_exists($key, $a);
}
return $result;
} else {
if(is_array($a) && array_key_exists($k, $a) && $a[$k])
return $a[$k];
elseif(is_object($a) && property_exists($a, $k) && $a->$k)
return $a->$k;
else
return $default;
}
}

+ 109
- 0
p3k/Geocoder.php View File

@ -0,0 +1,109 @@
<?php
namespace p3k;
class Geocoder {
public static function adrFromLocation($lat, $lng) {
$response = self::_reverse($lat, $lng);
if(!$response)
return false;
$address = $response->address;
$result = new geocode\Result;
$result->latitude = $lat;
$result->longitude = $lng;
if(property_exists($address, 'Postal'))
$result->postalCode = $address->Postal;
if(property_exists($address, 'Region'))
$result->regionName = $address->Region;
if(property_exists($address, 'City'))
$result->localityName = $address->City;
elseif(property_exists($address, 'Subregion'))
$result->localityName = $address->Subregion;
elseif(property_exists($address, 'Neighborhood'))
$result->localityName = $address->Neighborhood;
if(property_exists($address, 'CountryCode'))
$result->countryName = $address->CountryCode;
return $result;
}
public static function geocode($input) {
$response = self::_geocode($input);
if(!$response || count($response->locations) == 0)
return false;
$location = $response->locations[0];
$attributes = $location->feature->attributes;
$geometry = $location->feature->geometry;
$result = new geocode\Result;
if($geometry) {
$result->latitude = $geometry->y;
$result->longitude = $geometry->x;
}
if($attributes->City)
$result->localityName = $attributes->City;
if($attributes->Region)
$result->regionName = $attributes->Region;
if($attributes->Country)
$result->countryName = $attributes->Country;
if($attributes->Postal)
$result->postalCode = $attributes->Postal;
if($location->name)
$result->fullAddress = $location->name;
return $result;
}
private static function _reverse($lat, $lng) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode?location='.$lng.'%2C'.$lat.'&outSR=4326&f=json&distance=10000');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
// curl_setopt($ch, CURLOPT_USERAGENT, '');
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$result = curl_exec($ch);
if($result == FALSE)
return FALSE;
return json_decode($result);
}
private static function _geocode($input) {
$ch = curl_init();
$params = [
'f' => 'json',
'outSR' => 4326,
'text' => $input,
'outFields' => 'City,Region,Country,Postal',
];
curl_setopt($ch, CURLOPT_URL, 'http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find?' . http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
// curl_setopt($ch, CURLOPT_USERAGENT, '');
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$result = curl_exec($ch);
if($result == FALSE)
return FALSE;
return json_decode($result);
}
}

+ 22688
- 0
p3k/Timezone.php
File diff suppressed because it is too large
View File


+ 41
- 0
p3k/geocode/Result.php View File

@ -0,0 +1,41 @@
<?php
namespace p3k\geocode;
class Result {
public $latitude = null;
public $longitude = null;
public $fullAddress = null;
public $localityName = null;
public $regionName = null;
public $countryName = null;
public $postalCode = null;
private function _full_name() {
$parts = array();
if($this->localityName)
$parts[] = $this->localityName;
if($this->regionName)
$parts[] = $this->regionName;
if($this->countryName)
$parts[] = $this->countryName;
return implode(', ', $parts);
}
private function _best_name() {
if($this->localityName)
return $this->localityName;
if($this->regionName)
return $this->regionName;
if($this->countryName)
return $this->countryName;
return FALSE;
}
public function __get($key) {
if($key == 'fullName')
return $this->_full_name();
if($key == 'bestName')
return $this->_best_name();
return NULL;
}
}

+ 33
- 0
p3k/timezone/Result.php View File

@ -0,0 +1,33 @@
<?php
namespace p3k\timezone;
use DateTime, DateTimeZone;
class Result {
public $timezone = null;
private $_now;
private $_name;
public function __construct($timezone) {
$this->_now = new DateTime();
$this->_now->setTimeZone(new DateTimeZone($timezone));
$this->_name = $timezone;
}
public function __get($key) {
switch($key) {
case 'offset':
return $this->_now->format('P');
case 'seconds':
return (int)$this->_now->format('Z');
case 'localtime':
return $this->_now->format('c');
case 'name':
return $this->_name;
}
}
public function __toString() {
return $this->_name;
}
}

+ 15
- 0
public/.htaccess View File

@ -0,0 +1,15 @@
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

+ 11
- 0
public/index.php View File

@ -0,0 +1,11 @@
<?php
chdir('..');
require 'vendor/autoload.php';
\Slim\Savant\init();
require 'controllers/main.php';
require 'controllers/timezone.php';
require 'controllers/geocode.php';
$app->run();

+ 29
- 0
views/index.php View File

@ -0,0 +1,29 @@
<h2>Timezone</h2>
<h3>Retrieving the timezone at a lat/lng</h3>
<ul>
<li><a href="/api/timezone?latitude=45.5118&amp;longitude=-122.6433">/api/timezone?latitude=45.5118&amp;longitude=-122.6433</a></li>
</ul>
<h2>Geocoder</h2>
<h3>Retrieving the lat/lng for a named location</h3>
<ul>
<li><a href="/api/geocode?input=309+SW+6th+Ave,+Portland,+OR">/api/geocode?input=309+SW+6th+Ave,+Portland,+OR</a></li>
</ul>
<h3>Retrieving a named location from a lat/lng</h3>
<ul>
<li><a href="/api/geocode?latitude=45.5118&amp;longitude=-122.6433">/api/geocode?latitude=45.5118&amp;longitude=-122.6433</a></li>
</ul>
<h2>Context</h2>
<h3>Retrieving both the city name and timezone data for a lat/lng</h3>
<ul>
<li><a href="/api/context?latitude=45.5118&amp;longitude=-122.6433">/api/context?latitude=45.5118&amp;longitude=-122.6433</a></li>
</ul>

+ 19
- 0
views/layout.php View File

@ -0,0 +1,19 @@
<!doctype html>
<html>
<head>
<title>Atlas</title>
<link rel="stylesheet" href="/assets/pure-0.6.0/pure-min.css">
<link rel="stylesheet" href="/assets/pure-0.6.0/grids-responsive-min.css">
<link rel="stylesheet" href="/assets/font-awesome-4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" href="/assets/styles.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<?= $this->fetch($this->page . '.php') ?>
<footer>
&copy; 2015 by Aaron Parecki
</footer>
</body>
</html>

Loading…
Cancel
Save