Commit e1f7614e authored by thejoelinux's avatar thejoelinux

ajout service REST et adaptation des controlleurs

parent 318d2a6f
......@@ -18,8 +18,115 @@ new session_saas();
global $data;
$data = new data();
if(array_key_exists("handler", $_REQUEST)) {
// get ride of the trailing slash
$h = rtrim($_REQUEST["handler"],"/");
$array = preg_split('%/%', $h);
// anyway the first part is ALWAYS the controller
$_REQUEST["o"] = $array[0]; // first part becomes the controller
// process angular posted data in json
if(array_key_exists("CONTENT_TYPE", $_SERVER) && preg_match("%application/json%", $_SERVER["CONTENT_TYPE"])) {
$request = get_object_vars(json_decode(file_get_contents("php://input")));
while(list($key, $val) = each($request)) {
$_REQUEST[$key] = $val;
if($key == "id") {
$_REQUEST["i"] = $val; // that's ugly
}
}
}
// DEBUG header("Content-Type: text/plain"); print_r($_SERVER);
// parsing done according to this resource :
// http://www.restapitutorial.com/lessons/httpmethods.html
switch($_SERVER["REQUEST_METHOD"]) {
case "GET":
if(sizeof($array) > 1) { // stg like : GET /games/12345
$_REQUEST["i"] = $array[1];
if(sizeof($array) == 2) {
$_REQUEST["a"] = "edit";
}
}
if(sizeof($array) > 2) { // stg like : GET /games/12345/loans
$_REQUEST["a"] = $array[2];
}
if(sizeof($array) > 3) { // stg like : GET /games/12345/loans/56
// loans => loan_id
$_REQUEST[rtrim($array[2],"s")."_id"] = $array[3];
}
if(sizeof($array) > 4) {
App::http_error(400);
exit();
}
break;
case "POST":
switch(sizeof($array)) {
case 2:
case 4:
// stg like : POST /games/12345 or POST /games/12/loans/15
App::http_error(409); // you can't POST on a existing id
exit();
break;
case 1:
// stg like : POST /games/
$_REQUEST["a"] = "create";
break;
case 3:
// stg like : POST /games/1/loans
$_REQUEST["i"] = $array[1];
$_REQUEST["a"] = "create_".rtrim($array[2],"s"); // create_loan
break;
default:
App::http_error(400);
exit();
}
break;
case "PUT":
// angular ngResource PUT /object w/id in the json, so deal w/it
if(sizeof($array) > 1) {
// FIXME : i don't process PUT /games/1/loans for the moment
App::http_error(400);
exit();
}
$_REQUEST["a"] = "update";
// i has already been set before w/decoding the posted json
break;
case "PATCH":
if(sizeof($array) == 1) {
// unless you want to modify the collection itself.
header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404);
exit();
}
break;
case "DELETE":
if(sizeof($array) == 1) {
// unless you want to delete the whole collection—not often desirable.
header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404);
exit();
}
break;
default:
phpinfo();
exit();
}
}
// this is a json-only zone
header("Content-Type: application/json");
if(array_key_exists("o", $_REQUEST) && $_REQUEST["o"] != ""
&& file_exists("controllers/".$_REQUEST["o"].".php")) {
// call of the controller
......@@ -28,4 +135,5 @@ if(array_key_exists("o", $_REQUEST) && $_REQUEST["o"] != ""
$ctrl = new $controller();
} else {
header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', true, 400);
echo '{ "error": "'.$_SERVER["QUERY_STRING"].'"}';
}
......@@ -44,6 +44,16 @@ class data {
return mysqli_real_escape_string($this->db_handle, $string);
}
public function find($query, &$rset, $object) {
$this->select($query, $rset, $object);
if(!is_object($rset)) {
error_log("object not found : ".preg_replace('!\s+!', ' ', $query));
throw new object_not_found_exception(
"Object not found");
}
return $rset;
}
/*
* Execute a select query
* @param $query the select sql statement to execute
......
......@@ -34,7 +34,7 @@ class Game extends Record {
LEFT OUTER JOIN ".Reservation::$table." r ON (g.id = r.game_id)
LEFT OUTER JOIN ".Member::$table." m ON (r.member_id = m.id)
WHERE g.id = ".$id;
$GLOBALS["data"]->select($sql, $game, "Game");
$GLOBALS["data"]->find($sql, $game, "Game");
return $game;
}
......
<?php
class object_not_found_exception extends Exception {
public $error_message;
public function __construct ($error, Exception $previous = null) {
$this->error_message = $error;
if ( $previous instanceof Exception) {
parent::__construct($error, $previous);
} else {
parent::__construct($error);
}
}
// custom string representation of object
public function __toString() {
return $this->error_message;
}
public function to_json() {
return '{"message":"Object not found exception : '.$this->error_message.'"}';
}
}
......@@ -62,7 +62,7 @@ class AppController {
// DEBUG $this->twig->addExtension(new Twig_Extension_Debug());
$this->context["global"] = $GLOBALS;
$this->context["request"] = $_REQUEST;
$this->format = (preg_match("/api.php/", $_SERVER["REQUEST_URI"])) ? "json" : "html";
$this->format = (preg_match("/api.php/", $_SERVER["SCRIPT_NAME"])) ? "json" : "html";
if(!array_key_exists("user", $_SESSION)) {
return;
......@@ -87,6 +87,27 @@ class AppController {
}
}
public static function http_error($code = 500) {
switch($code) {
case "400":
header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', true, 400);
break;
case "404":
header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404);
break;
case "409":
header($_SERVER['SERVER_PROTOCOL'] . ' 409 Conflict', true, 409);
break;
case "500":
default:
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
break;
}
}
// pass objects to the context
public function set($var, &$val) {
$this->context[$var] = $val;
......@@ -175,18 +196,14 @@ class AppController {
}
function _edit($success = "edit") {
try {
$classname = $this->model;
$object = $classname::fetch($GLOBALS["data"]->db_escape_string($_REQUEST["i"]));
if($object->id != 0) {
$this->set("object", $object);
return $_REQUEST["o"]."/".$success;
} else {
return $_REQUEST["o"]."/not_found"; // TODO
}
} catch(data_exception $e) {
return "data_exception";
}
$classname = $this->model;
$object = $classname::fetch($GLOBALS["data"]->db_escape_string($_REQUEST["i"]));
if($this->format == "json") {
echo json_encode($object);
exit();
}
$this->set("object", $object);
return $_REQUEST["o"]."/".$success;
}
function _update() {
......@@ -249,34 +266,25 @@ class AppController {
}
function _list($method = "fetch_all") {
$format = (preg_match("/api.php/", $_SERVER["REQUEST_URI"])) ? "json" : "html";
try {
$objects = array();
$classname = $this->model;
$classname::$method($objects);
if($format == "json") {
// send dt_format=1 in URL to send format for datatables
if(array_key_exists("dt_format", $_REQUEST)) {
echo "{
\"sEcho\": 1,
\"iTotalRecords\": ".sizeof($objects).",
\"iTotalDisplayRecords\": ".sizeof($objects).",
\"data\":";
echo (sizeof($objects) ? json_encode($objects) : "[]")."}";
} else {
echo json_encode($objects);
}
exit(); // no further rendering needed
}
$this->set("objects", $objects);
return $_REQUEST["o"]."/list";
} catch(data_exception $e) {
if($format == "json") {
header($_SERVER['SERVER_PROTOCOL'] . ' Internal Server Error', true, 500);
exit(); // no further rendering needed
$objects = array();
$classname = $this->model;
$classname::$method($objects);
if($this->format == "json") {
// send dt_format=1 in URL to send format for datatables
if(array_key_exists("dt_format", $_REQUEST)) {
echo "{
\"sEcho\": 1,
\"iTotalRecords\": ".sizeof($objects).",
\"iTotalDisplayRecords\": ".sizeof($objects).",
\"data\":";
echo (sizeof($objects) ? json_encode($objects) : "[]")."}";
} else {
echo json_encode($objects);
}
return "data_exception";
}
exit(); // no further rendering needed
}
$this->set("objects", $objects);
return $_REQUEST["o"]."/list";
}
}
......@@ -2,11 +2,30 @@
class GamesController extends AppController {
public $model = "Game";
function GamesController() {
$this->AppController();
$function_name = "_".$_REQUEST["a"];
// to the view
$this->render($this->$function_name());
try {
$render = $this->$function_name();
} catch (object_not_found_exception $e) {
$this->http_error(404);
if($this->format == "json") {
echo "{}";
exit();
}
$render = $_REQUEST["o"]."/not_found"; // TODO
} catch (data_exception $e) {
$this->http_error(500);
if($this->format == "json") {
exit();
}
$render = "data_exception";
}
// view part
$this->render($render);
}
function _index() {
......@@ -32,34 +51,21 @@ class GamesController extends AppController {
}
function _update() {
try {
$game = Game::fetch($GLOBALS["data"]->db_escape_string($_REQUEST["i"]));
if($game->id != 0) {
$game->update();
$_REQUEST["a"] = "edit";
$this->set("game", $game);
$render = "games/edit";
} else {
$render = "games/not_found"; // TODO
}
} catch(data_exception $e) {
$render = "data_exception";
}
return($render);
$game = Game::fetch($GLOBALS["data"]->db_escape_string($_REQUEST["i"]));
$game->update();
$_REQUEST["a"] = "edit";
$this->set("game", $game);
return "games/edit";
}
function _edit() {
try {
$game = Game::fetch($GLOBALS["data"]->db_escape_string($_REQUEST["i"]));
if($game->id != 0) {
$this->set("game", $game);
return "games/edit";
} else {
return "games/not_found"; // TODO
}
} catch(data_exception $e) {
return "data_exception";
}
$game = Game::fetch($GLOBALS["data"]->db_escape_string($_REQUEST["i"]));
if($this->format == "json") {
echo json_encode($game);
exit();
}
$this->set("game", $game);
return "games/edit";
}
function _name_list() { // for API
......@@ -164,6 +170,10 @@ class GamesController extends AppController {
function _list() {
try {
Game::fetch_all($games);
if($this->format == "json") {
echo json_encode($games);
exit();
}
$this->set("games", $games);
$render = "games/list";
} catch(data_exception $e) {
......
......@@ -6,10 +6,26 @@ class LoansController extends AppController {
function LoansController() {
$this->AppController();
$function_name = "_".$_REQUEST["a"];
// to the view
$this->render($this->$function_name());
try {
$render = $this->$function_name();
} catch (object_not_found_exception $e) {
$this->http_error(404);
if($this->format == "json") {
echo "{}";
exit();
}
$render = $_REQUEST["o"]."/not_found"; // TODO
} catch (data_exception $e) {
$this->http_error(500);
if($this->format == "json") {
exit();
}
$render = "data_exception";
}
// view part
$this->render($render);
}
function _index() {
......@@ -43,18 +59,17 @@ class LoansController extends AppController {
}
function _list() {
$format = (preg_match("/api.php/", $_SERVER["REQUEST_URI"])) ? "json" : "html";
try {
$classname = $this->model;
$classname::fetch_current_loans($objects);
if($format == "json") {
if($this->format == "json") {
echo json_encode($objects);
exit(); // no further rendering needed
}
$this->set("objects", $objects);
return $_REQUEST["o"]."/list";
} catch(data_exception $e) {
if($format == "json") {
if($this->format == "json") {
header($_SERVER['SERVER_PROTOCOL'] . ' Internal Server Error', true, 500);
exit(); // no further rendering needed
}
......
......@@ -8,6 +8,28 @@ class PaymentMethodsController extends AppController {
$function_name = "_".$_REQUEST["a"];
// to the view
$this->render($this->$function_name());
try {
$render = $this->$function_name();
} catch (object_not_found_exception $e) {
$this->http_error(404);
if($this->format == "json") {
echo "{}";
exit();
}
$render = $_REQUEST["o"]."/not_found"; // TODO
} catch (data_exception $e) {
$this->http_error(500);
if($this->format == "json") {
exit();
}
$render = "data_exception";
}
// view part
$this->render($render);
}
function _index() {
return $this->_list();
}
}
RewriteCond %{REQUEST_URI} !(.*)\.(css|js|htc|pdf|jpg|jpeg|gif|png|ico)$ [NC]
RewriteRule ^(.*)$ ../api.php?handler=$1 [QSA,L]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment