| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 | <?php/** * Classe de gestion des API (REST). * @author Valentin CARRUESCO * @category Plugin * @license copyright */class Api{	public $slug,$description;	function __construct($slug=null,$description=null){		if(isset($slug)) $this->slug = $slug;		if(isset($description)) $this->description = $description;		$this->route = array();		return $this;	}	function route($slug = null,$description = null,$method = null,$callback){		$route =  new ApiRoute($slug,$description,$method,$callback);		$this->route[$route->slug][$method] = $route;	}	function register(){		Plugin::addHook('api',function(&$apis){			$apis[$this->slug] = $this;					});	}	public static function run(){		global $_,$myUser;		$response = array();		try{			/*set_error_handler(function( $errno ,  $errstr , $errfile ,  $errline){				throw new Exception("Error ".$errno." Processing Request ".$errfile.$errstr, 500);			});			register_shutdown_function(function( $errno ,  $errstr , $errfile ,  $errline){				$error = error_get_last();				throw new Exception("Error ".E_CORE_ERROR." Processing Request ".$error['file'], 500);			});*/			$command = explode('/',$_['command']);			if(count($command)<1) throw new Exception("Unspecified API");			$headers = apache_request_headers();						//basic auth			if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])){				$user = User::check($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']);				if(!$user) throw new Exception('Le compte spécifié est inexistant');				$myUser = $user;			}			$request = array(				'version' =>array_shift($command),				'module' =>array_shift($command),				'route' =>array_shift($command),				'body' =>file_get_contents("php://input"),				'method' => strtoupper($_SERVER['REQUEST_METHOD']),				'parameters' => $_,				'pathes' => array_filter($command)			);						$code = 200;			$headers = array(				'Content-Type: application/json'			);			$apis = array();			Plugin::callHook('api',array(&$apis));			//format de l'url : /api/v{version}/			if(!isset($request['version']) || !is_numeric(substr($request['version'],1)) || substr($request['version'], 0,1)!='v') throw new Exception("Api version is missing or invalid, specify ".ROOT_URL."/api/{version} for valid requests", 404);			if($request['module'] == 'schema'){				foreach ($apis as $api) {					$routes= array();					foreach($api->route as $route){												foreach($route as $method=>$infos){							if(!isset($routes[$infos->slug])) $routes[$infos->slug] = array() ;							$routes[$infos->slug][] = $infos->method.' '.$api->slug .'/'.$infos->pattern .': '. $infos->description ;						}					}					$response[] =  array( $api->slug => $api->description,'routes'=> $routes);				}			}else{				if(!isset($apis[$request['module']])) throw new Exception("Api '".$request['module']."' is missing, see ".ROOT_URL."/api/schema for available calls", 404);				$api = $apis[$request['module']];												if(!isset($api->route[$request['route']]))  throw new Exception("Route '".$api->slug.'/'.$request['route']."' is missing, see ".ROOT_URL."/api/schema?pretty for available calls", 404);				$route = $api->route[$request['route']];								if(!isset($route[$request['method']]))  throw new Exception("Method ".$request['method']." '".$api->slug.'/'.$route->slug."' is not allowed", 405);				$method = $route[$request['method']];				$callback = $method->callback;								$callback($request,$response);				if(isset($response['code'])) $code = $response['code'];				if(isset($response['headers'])) $headers = array_merge($headers,$response['headers']);				unset($response['code']);				unset($response['headers']);			}					}catch(Exception $e){			$response['error'] = $e->getMessage();			$code = $e->getCode();			if(empty($code) || $code==0)  $code = 666;		}		$codes = array(			200 => 'HTTP/1.1 200 Ok',			201 => 'HTTP/1.1 201 Created',			204 => 'HTTP/1.1 204 No Content',			207 => 'HTTP/1.1 207 Multi-Status',			400 => 'HTTP/1.0 400 Bad Request',			401 => 'HTTP/1.0 401 Unauthorized',			403 => 'HTTP/1.1 403 Forbidden',			404 => 'HTTP/1.1 404 Not Found',			404 => 'HTTP/1.1 405 Method Not Allowed',			406 => 'HTTP/1.1 406 Not acceptable',			409 => 'HTTP/1.1 409 Conflict',			415 => 'HTTP/1.1 415 Unsupported Media Type',			423 => 'HTTP/1.1 423 Locked',			500 => 'HTTP/1.1 500 Internal Server Error',			501 => 'HTTP/1.1 501 Not implemented',			666 => 'HTTP/1.1 666 Welcome to Hell mate!',		);		if (ob_get_length()) ob_end_clean();		header(isset($codes[$code]) ? $codes[$code] : $codes[666]);				foreach ($headers as $header) {			header($header);		}				if(isset($_['pretty'])){			echo json_encode($response,JSON_PRETTY_PRINT);		}else{			echo json_encode($response);		}		exit();	}}class ApiRoute{	public $slug,$description,$callback,$method,$pathes,$parameters,$pattern;	function __construct($slug='default',$description='No description',$method='GET',$callback){		$this->pattern = $slug;		$infos = explode('?',$slug);		if(isset($infos[1])) $this->parameters = $infos[1];		$infos = explode('/',$infos[0]);		$this->slug = array_shift($infos);		$this->pathes = $infos;		$this->description = $description;		$this->method = $method;		$this->callback = $callback;	}}?>
 |