WIP AddressDB + api
This commit is contained in:
@@ -0,0 +1,546 @@
|
||||
<?php
|
||||
|
||||
// include BaseModel if available
|
||||
include_once(realpath(dirname(__FILE__))."/mfBaseModel.php");
|
||||
|
||||
class mfBaseApicontroller {
|
||||
protected $log;
|
||||
protected $needlogin = false;
|
||||
protected $siteTitle;
|
||||
private $mfAction;
|
||||
private $mfDBI;
|
||||
private $mfMenu;
|
||||
private $mfUser;
|
||||
protected $requireAuth = true;
|
||||
protected $me;
|
||||
protected $mod;
|
||||
protected $action;
|
||||
protected $apiversion;
|
||||
protected $headers = [];
|
||||
protected $route;
|
||||
protected $get = [];
|
||||
protected $post = [];
|
||||
protected $format = "default";
|
||||
|
||||
private $http_method;
|
||||
private $routes = [];
|
||||
|
||||
public function __construct($params = NULL) {
|
||||
// load logging facility
|
||||
$this->log = mfLoghandler::singleton();
|
||||
$this->loadRequest($params);
|
||||
|
||||
register_shutdown_function(["mfBaseApicontroller", "return_errors"]);
|
||||
|
||||
// run Controllers init() function
|
||||
if(method_exists($this,"init")) {
|
||||
$this->init();
|
||||
}
|
||||
|
||||
if($this->requireAuth) {
|
||||
$this->authenticateUser();
|
||||
}
|
||||
|
||||
// route to action
|
||||
$this->route = $params['apicall'].(($params['apiparams']) ? $params['apiparams'] : "");
|
||||
$responseData = $this->runRoute($this->route);
|
||||
|
||||
if(!$responseData) {
|
||||
$this->return(mfResponse::InternalServerError());
|
||||
}
|
||||
|
||||
// return respnse
|
||||
$this->return($responseData);
|
||||
|
||||
}
|
||||
|
||||
private function authenticateUser() {
|
||||
$key = false;
|
||||
//var_dump($this->headers);exit;
|
||||
if(array_key_exists("x-api-key", $this->headers) && $this->headers['x-api-key']) {
|
||||
$key = $this->headers['x-api-key']; // change to X-Auth-Token
|
||||
}
|
||||
if(array_key_exists("apikey", $this->get)) {
|
||||
$key = $this->get['apikey']; // token
|
||||
}
|
||||
|
||||
$me = new User;
|
||||
$me->loadByApikey($key);
|
||||
|
||||
if(!$me->id) {
|
||||
$this->return(mfResponse::Unauthorized(['message' => "API key missing or invalid"]));
|
||||
}
|
||||
$_SESSION[MFAPPNAME.'_username'] = $me->username;
|
||||
$this->log->info("Authenticated '".$me->username."' with api key");
|
||||
$this->me = $me;
|
||||
}
|
||||
|
||||
private function loadRequest($params) {
|
||||
foreach(apache_request_headers() as $header => $value) {
|
||||
$this->headers[strtolower($header)] = $value;
|
||||
}
|
||||
// GET parameters
|
||||
$get = $params;
|
||||
unset($get['mod']);
|
||||
unset($get['action']);
|
||||
unset($get['apiv']);
|
||||
unset($get['apicall']);
|
||||
unset($get['apiparams']);
|
||||
unset($get['http_method']);
|
||||
$this->get = $get;
|
||||
$this->mod = $params['mod'];
|
||||
$this->action = $params['action'];
|
||||
|
||||
// check for api version
|
||||
$apiversion = API_VERSION;
|
||||
if($params['apiv'] && $params['apiv'] != $apiversion) {
|
||||
$apiversion = $params['apiv'];
|
||||
}
|
||||
$this->apiversion = $apiversion;
|
||||
$this->http_method = strtoupper($_SERVER['REQUEST_METHOD']);
|
||||
|
||||
if($this->http_method == "BREW") {
|
||||
// easter egg :)
|
||||
$this->return(mfResponse::ImATeaPot());
|
||||
}
|
||||
|
||||
// CORS preflight OPTIONS
|
||||
// CORS headers must be correctly set in .htaccess or vhost config
|
||||
if($this->http_method == "OPTIONS") {
|
||||
$this->return(mfResponse::Ok());
|
||||
}
|
||||
|
||||
// POST Request
|
||||
$post = [];
|
||||
if($this->http_method == "POST") {
|
||||
$post = $this->getPostRequest();
|
||||
if($post === false) {
|
||||
$post = [];
|
||||
//$this->return(mfResponse::BadRequest(["message" => "Invalid request body; expected Form-Urlencoded or JSON format"]));
|
||||
}
|
||||
$this->post = $post;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getPostRequest() {
|
||||
$body = $this->getRequestBody();
|
||||
if(is_array($body)) {
|
||||
// request is parsed already ($_POST)
|
||||
return $body;
|
||||
}
|
||||
|
||||
// otherwise request likely is json
|
||||
$json_request = json_decode($body);
|
||||
if(json_last_error() === JSON_ERROR_NONE) {
|
||||
//var_dump((array)$json_request);exit;
|
||||
return (array)$json_request;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getRequestBody() {
|
||||
if($_SERVER["CONTENT_TYPE"] == "application/json") {
|
||||
$request_body = file_get_contents('php://input');
|
||||
return $request_body;
|
||||
}
|
||||
|
||||
return $_POST;
|
||||
|
||||
}
|
||||
|
||||
protected function return($response) {
|
||||
//var_dump($response);exit;
|
||||
$code = 500;
|
||||
$status = "Internal Server Error";
|
||||
$data = [];
|
||||
|
||||
if($response['code']) {
|
||||
$code = $response['code'];
|
||||
}
|
||||
if($response['status']) {
|
||||
$status = $response['status'];
|
||||
}
|
||||
if(is_array($response['data'])) {
|
||||
$data = $response['data'];
|
||||
}
|
||||
|
||||
$proto = "HTTP/1.0";
|
||||
if($_SERVER["SERVER_PROTOCOL"]) {
|
||||
$proto = $_SERVER["SERVER_PROTOCOL"];
|
||||
}
|
||||
header("$proto $code $status");
|
||||
header("Content-type: application/json");
|
||||
//http_response_code($code);
|
||||
echo json_encode(["status" => $status, "result" => $data]);
|
||||
exit;
|
||||
}
|
||||
|
||||
public static function staticReturn($response) {
|
||||
//var_dump($response);exit;
|
||||
$code = 500;
|
||||
$status = "Internal Server Error";
|
||||
$data = [];
|
||||
|
||||
if($response['code']) {
|
||||
$code = $response['code'];
|
||||
}
|
||||
if($response['status']) {
|
||||
$status = $response['status'];
|
||||
}
|
||||
if(is_array($response['data'])) {
|
||||
$data = $response['data'];
|
||||
}
|
||||
|
||||
$proto = "HTTP/1.0";
|
||||
if($_SERVER["SERVER_PROTOCOL"]) {
|
||||
$proto = $_SERVER["SERVER_PROTOCOL"];
|
||||
}
|
||||
header("$proto $code $status");
|
||||
header("Content-type: application/json");
|
||||
//http_response_code($code);
|
||||
echo json_encode(["status" => $status, "result" => $data]);
|
||||
exit;
|
||||
}
|
||||
|
||||
private function checkAuth() {
|
||||
|
||||
}
|
||||
|
||||
protected function runRoute($params) {
|
||||
if(!is_array($this->routes) || !count($this->routes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$params = trim($params, "/");
|
||||
$m = [];
|
||||
|
||||
if(preg_match('/\.(\w+)$/', $params, $m)) {
|
||||
if($m[1]) {
|
||||
$format = strtolower($m[1]);
|
||||
$params = preg_replace("/\.$format$/", "", $params);
|
||||
$this->format = $format;
|
||||
}
|
||||
}
|
||||
|
||||
//var_dump($params);exit;
|
||||
|
||||
$req_parts = explode("/", $params);
|
||||
$req_count = count($req_parts);
|
||||
|
||||
foreach($this->routes as $route) {
|
||||
if($route['method'] != $this->http_method) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$route_string = trim($route['route'], "/");
|
||||
$route_parts = explode("/", $route_string);
|
||||
$route_count = count($route_parts);
|
||||
|
||||
if($req_count != $route_count) {
|
||||
continue;
|
||||
}
|
||||
// same number of parts
|
||||
|
||||
$vars = [];
|
||||
foreach($route_parts as $i => $rp) {
|
||||
if(substr($rp,0,1) == ":") {
|
||||
// part is variable
|
||||
$var_name = substr($rp, 1);
|
||||
$vars[$var_name] = $req_parts[$i];
|
||||
continue;
|
||||
} else {
|
||||
if($rp != $req_parts[$i]) {
|
||||
continue 2; // break out of this loop and continue outer foreach
|
||||
}
|
||||
}
|
||||
}
|
||||
// found valid route
|
||||
return $this->call($route['action'], $vars);
|
||||
|
||||
}
|
||||
|
||||
// no route found
|
||||
$this->return(mfResponse::BadRequest());
|
||||
exit;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown handler to return PHP errors as API response.
|
||||
* Errors are still logged in error_log
|
||||
*/
|
||||
public static function return_errors() {
|
||||
$error = error_get_last();
|
||||
//var_dump($error);exit;
|
||||
|
||||
if($error && $error['type'] & (E_ERROR|E_CORE_ERROR|E_COMPILE_ERROR|E_USER_ERROR|E_RECOVERABLE_ERROR)) {
|
||||
mfBaseApicontroller::staticReturn(mfResponse::InternalServerError(["message" => "An internal error occured, please try again"]));
|
||||
}
|
||||
|
||||
|
||||
/*header("Content-type: application/json");
|
||||
http_response_code($code);
|
||||
echo json_encode(["status" => $status, "result" => $data]);
|
||||
exit;*/
|
||||
|
||||
}
|
||||
|
||||
private function call($function, $params = []) {
|
||||
if(count($params) === 1) {
|
||||
return $this->__call($function,reset($params));
|
||||
} else {
|
||||
return $this->__call($function,$params);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addRoute($route, $action, $method) {
|
||||
$this->routes[] = [
|
||||
"route" => $route,
|
||||
"action" => $action,
|
||||
"method" => $method
|
||||
];
|
||||
}
|
||||
|
||||
public static function loadApiClass($name) {
|
||||
//var_dump($name);exit;
|
||||
if(!$name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$folder = APPDIR."Api/".((defined("CURRENT_API_VERSION")) ? CURRENT_API_VERSION : API_VERSION);
|
||||
|
||||
$m = [];
|
||||
if(preg_match('/(.+)Apicontroller/',$name, $m)) {
|
||||
$classname = $m[1]."Apicontroller";
|
||||
$filename = "$classname.php";
|
||||
if(file_exists("$folder/$filename")) {
|
||||
require_once "$folder/$filename";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function user() {
|
||||
if(!MFUSELOGIN) {
|
||||
trigger_error("mvcfronk: Tried to access mfBaseController::user(), though MFUSELOGIN is set to false.", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
if(!$this->mfUser) {
|
||||
$this->mfUser=mfUser::singleton();
|
||||
}
|
||||
return $this->mfUser;
|
||||
}
|
||||
|
||||
|
||||
protected function db() {
|
||||
$args=func_get_args();
|
||||
|
||||
// if no arguments, just return a DB instance
|
||||
if(!$args) {
|
||||
// don't allow managed FronkDB instance, but new custom instance is allowed
|
||||
if(!FRONKDB) {
|
||||
return false;
|
||||
}
|
||||
if(!is_object($this->mfDBI)) {
|
||||
$this->mfDBI=FronkDB::singleton();
|
||||
|
||||
}
|
||||
return $this->mfDBI;
|
||||
} else {
|
||||
// else return a new instance
|
||||
var_dump($args);
|
||||
$dbhost=$args[0];
|
||||
$dbuser=$args[1];
|
||||
$dbpass=$args[2];
|
||||
$dbname=$args[3];
|
||||
return $this->getNewDBInstance($dbhost,$dbuser,$dbpass,$dbname);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function __call($name,$params) {
|
||||
if(method_exists($this,$name)) {
|
||||
return call_user_func(array($this, $name), $params);
|
||||
} else { // if function doesn't exist, maybe it's an Action
|
||||
$funcname=lcfirst($name);
|
||||
if(!preg_match('/Action$/',$name)) {
|
||||
$funcname.="Action";
|
||||
}
|
||||
|
||||
if(method_exists($this,$funcname)) {
|
||||
return call_user_func(array($this, $funcname), $params);
|
||||
} else {
|
||||
throw new Exception(get_class($this).": $name not found",404);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __get($name) {
|
||||
if($name == "db") {
|
||||
return $this->db();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected function logout() {
|
||||
mfLoginController::logout();
|
||||
$this->redirect(DEFAULT_ROUTE);
|
||||
}
|
||||
|
||||
/*
|
||||
* private internal functions
|
||||
*/
|
||||
|
||||
private function getNewDBInstance($dbhost=false,$dbuser=false,$dbpass=false,$dbname=false) {
|
||||
if(!$dbhost) $dbhost=FRONKDB_DBHOST;
|
||||
if(!$dbuser) $dbhost=FRONKDB_DBUSER;
|
||||
if(!$dbpass) $dbhost=FRONKDB_DBPASS;
|
||||
if(!$dbname) $dbname=FRONKDB_DBNAME;
|
||||
|
||||
return new FronkDB($dbhost,$dbuser,$dbpass,$dbname);
|
||||
}
|
||||
|
||||
public static function redirect($mod=false,$action=false,$params=false,$anker=false) {
|
||||
//var_dump($mod);
|
||||
//var_dump($action);
|
||||
|
||||
$log = mfLoghandler::singleton();
|
||||
|
||||
if(MFUSEFANCYURLS && defined('MFFANCYBASEURL')) {
|
||||
// use fancy urls
|
||||
$url=MFFANCYBASEURL;
|
||||
if($mod) {
|
||||
$url.="/$mod";
|
||||
if($action) {
|
||||
$url.="/$action";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no fancy urls
|
||||
if(!$mod) {
|
||||
$url="?";
|
||||
} elseif($mod) {
|
||||
$url="?action=$mod";
|
||||
if($action) {
|
||||
$url.="_$action";
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
if(is_array($params) && count($params)) {
|
||||
foreach($params as $k => $v) {
|
||||
$url.="&$k=$v";
|
||||
}
|
||||
}*/
|
||||
|
||||
if(is_array($params) && count($params)) {
|
||||
$url .= (MFUSEFANCYURLS) ? "/?" : "&";
|
||||
foreach($params as $k => $v) {
|
||||
$v = urlencode($v);
|
||||
|
||||
if($k) {
|
||||
$k = urlencode($k);
|
||||
$url .= "$k=$v&";
|
||||
} else {
|
||||
$url .= "$v&";
|
||||
}
|
||||
}
|
||||
|
||||
$url = preg_replace('/&$/', '', $url);
|
||||
}
|
||||
|
||||
if($anker) {
|
||||
$url.="#$anker";
|
||||
}
|
||||
|
||||
$log->debug("Redirecting to $url");
|
||||
header("Location: $url");
|
||||
exit;
|
||||
}
|
||||
|
||||
public static function getUrl($mod, $action=null, $param=null) {
|
||||
if(!$mod) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
if(MFUSEFANCYURLS) {
|
||||
// use fancy urls
|
||||
$url=MFFANCYBASEURL;
|
||||
if($mod) {
|
||||
$url.="/$mod";
|
||||
if($action) {
|
||||
$url.="/$action";
|
||||
}
|
||||
}
|
||||
$url = preg_replace('#//#','/',$url);
|
||||
} else {
|
||||
// no fancy urls
|
||||
$url="?action=$mod";
|
||||
if($action) {
|
||||
$url.="_$action";
|
||||
}
|
||||
}
|
||||
if(is_array($param) && count($param)) {
|
||||
$url .= (MFUSEFANCYURLS) ? "/" : "&";
|
||||
$param_qs = http_build_query($param);
|
||||
$url .= "$param_qs";
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public static function returnJson($data) {
|
||||
if(is_array($data)) {
|
||||
header("Content-Type: application/json");
|
||||
echo json_encode($data);
|
||||
exit;
|
||||
} else {
|
||||
throw new Exception("Data not an array");
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
|
||||
public static function dateToTimestamp($date) {
|
||||
$t = array(0,0,0);
|
||||
|
||||
// extract day, month, year
|
||||
if (!preg_match('/^(\d{1,2})\.(\d{1,2})\.(\d{2,4})/',$date,$d)) {
|
||||
return false;
|
||||
}
|
||||
// extract time if available
|
||||
if (preg_match('/(\d\d):(\d\d):(\d\d)$/',$date,$t)) {
|
||||
if (!$t[3]) {
|
||||
$t[3] = 0;
|
||||
}
|
||||
}
|
||||
// make and return timestamp
|
||||
$ts = mktime($t[1],$t[2],$t[3],$d[2],$d[1],$d[3]);
|
||||
return $ts;
|
||||
}
|
||||
|
||||
public static function dateToDB($date,$type='l') {
|
||||
// get timestamp
|
||||
$ts = self::dateToTimestamp($date);
|
||||
|
||||
// only proceed if timestamp conversion was successful
|
||||
if(!$ts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// return date and time if long type requested
|
||||
if($type = 'l') {
|
||||
$dbdate = date('Y-m-d H:i:s',$ts);
|
||||
} else {
|
||||
$dbdate = date('Y-m-d',$ts);
|
||||
}
|
||||
|
||||
return $dbdate;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user