Created
June 6, 2014 09:37
-
-
Save zetas/0b96cbaec9676de834ac to your computer and use it in GitHub Desktop.
Spartz Controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Created by DavidDV <[email protected]> | |
* For project Spartz | |
* Created: 6/3/14 | |
* <http://[github|bitbucket].com/zetas> | |
*/ | |
class APIController extends BaseController { | |
private $R = 6371; // Earth's mean radius in km | |
private function _pull($query, $single = false, $limit = 1000, $from = 0) { | |
if ($single) | |
return $query->firstOrFail(); | |
if ($query->count() == 0) { | |
App::abort(404); | |
} | |
return $query->skip($from)->take($limit)->get(); | |
} | |
private function _calculate_minmax($lat, $lon, $rad) { | |
$maxLat = $lat + rad2deg($rad/$this->R); | |
$minLat = $lat - rad2deg($rad/$this->R); | |
// compensate for degrees longitude getting smaller with increasing latitude | |
$maxLon = $lon + rad2deg($rad/$this->R/cos(deg2rad($lat))); | |
$minLon = $lon - rad2deg($rad/$this->R/cos(deg2rad($lat))); | |
return array('maxLat' => $maxLat, 'minLat' => $minLat, 'maxLon' => $maxLon, 'minLon' => $minLon); | |
} | |
public function showCities($state) { | |
// @TODO: Not dry, it's wet-as-hell actually, repeated in almost every action. Top priority refactor. | |
$limit = abs(Input::get('limit', 1000)); | |
$from = abs(Input::get('from', 0)); | |
$query = City::whereState($state); | |
return Response::json($this->_pull($query, false, $limit, $from)); | |
} | |
public function showCityRadius($state, $city) { | |
$limit = abs(Input::get('limit', 1000)); | |
$from = abs(Input::get('from', 0)); | |
$radiusMI = abs(Input::get('radius', 100)); | |
($radiusMI > 500) ? $radiusMI = 500 : null; #Cap radius at 500 | |
$ratio = 1.609344; //For converting MI to KM | |
$rad = $radiusMI*$ratio; | |
$query = City::whereState($state)->whereName($city); | |
$c = $this->_pull($query, true); | |
$minMax = $this->_calculate_minmax($c->latitude, $c->longitude, $rad); | |
$lat = deg2rad($c->latitude); | |
$lon = deg2rad($c->longitude); | |
/* | |
* Special thanks for this mathematical wonder go to | |
* http://www.movable-type.co.uk/scripts/latlong-db.html | |
*/ | |
$cities = City::select(DB::raw('id, name, state, latitude, longitude, acos(sin(?)*sin(radians(latitude)) + cos(?)*cos(radians(latitude))*cos(radians(longitude)-?)) * ? As D')) | |
->from(DB::raw('(Select id, name, state, latitude, longitude From cities Where latitude Between ? And ? And longitude Between ? And ?) As FirstCut')) | |
->whereRaw('acos(sin(?)*sin(radians(latitude)) + cos(?)*cos(radians(latitude))*cos(radians(longitude)-?)) * ? < ? AND id != ?') | |
->orderBy('D') | |
->skip($from)->take($limit) | |
->setBindings([$lat, $lat, $lon, $this->R, $minMax['minLat'], $minMax['maxLat'], $minMax['minLon'], $minMax['maxLon'], $lat, $lat, $lon, $this->R, $rad, $c->id]) | |
->get(); | |
return Response::json($cities); | |
} | |
public function showVisits($user) { | |
$limit = abs(Input::get('limit', 1000)); | |
$from = abs(Input::get('from', 0)); | |
$u = User::findOrFail($user); | |
$visits = $u->visits()->skip($from)->take($limit)->get(); | |
return View::make('visits', array('visits' => $visits)); | |
} | |
/** | |
* Notes: | |
* I figure we allow them to save multiple visits to the same place, | |
* maybe it's a travel log. | |
*/ | |
public function addVisit($user) { | |
// @TODO: Not Dry. Also, insecure. (you could hammer user id's to find which is legit) | |
$u = User::findOrFail($user); | |
$json = Input::get('json'); | |
$data = json_decode($json, true); | |
if (!array_key_exists('city', $data) || !array_key_exists('state', $data)) | |
App::abort(404, 'Improperly formatted JSON.'); | |
/* | |
* @TODO: Not Dry, put this common query into a model scope, and the _pull as a validator. | |
* In addition, we're using inputs directly in a query builder statement. Hopefully the QB escapes it. | |
* If this were a real project, i'd need to research this and possibly fix it with proper validators. | |
*/ | |
$query = City::whereState($data['state'])->whereName($data['city']); | |
$c = $this->_pull($query, true); | |
// @TODO: Fix this to use the ORM to manage the relationship. | |
$visit = new Visit(); | |
$visit->city_id = $c->id; | |
$visit->user_id = $u->id; | |
$visit->save(); | |
/* | |
* Since we would have generated an error by now if something was wrong... | |
* | |
* Might want to change this to a simple redirect back to the list but as | |
* I assume this would be for an api, redirecting on completion is not ideal. | |
*/ | |
return 'Added!'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment