array); default: throw new Exception('Unknown type: ' . $clz); } } public static function Object2XML($o) { $clz = get_class($o); $res = sprintf('<%s>', strtolower($clz)); switch($clz) { // simple data classes case 'T1': foreach(get_object_vars($o) as $nam => $val) { $res .= sprintf('<%s>%s', $nam, $val, $nam); } break; // array wrapper classes case 'T1Array': foreach($o->array as $elm) { $res .= Util::Object2XML($elm); } break; default: throw new Exception('Unknown type: ' . $clz); } $res .= sprintf('', strtolower($clz)); return $res; } public static function Object2String($o, $typ) { if($typ == 'application/xml') { return Util::Object2XML($o); } else if($typ == 'application/json') { return Util::Object2JSON($o); } else { throw new Exception('Unknown type: ' . $typ); } } public static function XML2Object($clz, $xml) { $temp = simplexml_load_string($xml); $res = new $clz(); switch($clz) { // simple data classes case 'T1': foreach(get_object_vars($res) as $nam => $val) { if(is_int($res->$nam)) { $res->$nam = (int)$temp->$nam; } else { $res->$nam = (string)$temp->$nam; } } break; // array wrapper classes case 'T1Array': $elmclz = substr($clz, 0, -5); foreach($temp as $elm) { $o = new $elmclz(); foreach(get_object_vars($o) as $nam => $val) { if(is_int($o->$nam)) { $o->$nam = (int)$elm->$nam; } else { $o->$nam = (string)$elm->$nam; } } $res->array[] = $o; } break; default: throw new Exception('Unknown type: ' . $clz); } return $res; } public static function JSON2Object($clz, $json) { $temp = json_decode($json); $res = new $clz(); switch($clz) { // simple data classes case 'T1': foreach(get_object_vars($res) as $nam => $val) { $res->$nam = $temp->$nam; } break; // array wrapper classes case 'T1Array': $elmclz = substr($clz, 0, -5); foreach($temp as $elm) { $o = new $elmclz(); foreach(get_object_vars($o) as $nam => $val) { $o->$nam = $elm->$nam; } $res->array[] = $o; } break; default: throw new Exception('Unknown type: ' . $clz); } return $res; } public static function String2Object($clz, $s, $typ) { if($typ == 'application/xml') { return Util::XML2Object($clz, $s); } else if($typ == 'application/json') { return Util::JSON2Object($clz, $s); } else { throw new Exception('Unknown type: ' . $typ); } } } class T1 { public $f1; public $f2; public function __construct($f1 = 0, $f2 = '') { $this->f1 = $f1; $this->f2 = $f2; } } class T1Array { public $array; public function __construct($array = array()) { $this->array = $array; } } class Test { public function getOne($f1) { // dummy implementation return new T1($f1, 'getOne'); } public function getAll() { // dummy implementation $res = array(); $res[] = new T1(1, 'getAll #1'); $res[] = new T1(2, 'getAll #2'); $res[] = new T1(3, 'getAll #3'); return $res; } public function getSome($start, $finish) { // dummy implementation $res = array(); for($i = 0; $i < $finish - $start + 1; $i++) { $res[] = new T1($start + $i, 'getSome #' . ($start + $i)); } return $res; } public function save($o) { // dummy implementation return $o->f1 > 0 && strlen($o->f2) > 0; } public function delete($f1) { // dummy implementation return $f1 > 0; } } function read_request_body($clz) { $contyp = $_SERVER['CONTENT_TYPE']; $contyp = explode(';', $contyp)[0]; $body = file_get_contents("php://input"); return Util::String2Object($clz, $body, $contyp); } require_once 'lib/limonade.php'; ////function before($route) { //// header("Access-Control-Allow-Origin: *"); ////} dispatch_get('/t1', 'get_all_or_some'); function get_all_or_some() { $acctyp = $_SERVER['HTTP_ACCEPT']; $real = new Test(); if(isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']) > 0) { parse_str($_SERVER['QUERY_STRING'], $q); $a = $real->getSome($q['start'], $q['finish']); } else { $a = $real->getAll(); } header('Content-Type: ' . $acctyp); return Util::Object2String(new T1Array($a), $acctyp); } dispatch_get('/t1/:f1', 'get_one'); function get_one($f1) { $acctyp = $_SERVER['HTTP_ACCEPT']; $real = new Test(); $o = $real->getOne((int)$f1); header('Content-Type: ' . $acctyp); return Util::Object2String($o, $acctyp); } dispatch_post('/t1', 'save'); function save() { $acctyp = $_SERVER['HTTP_ACCEPT']; $o = read_request_body('T1'); $real = new Test(); if($real->save($o)) { header('Content-Type: ' . $acctyp); return Util::Object2String($o, $acctyp); } else { halt(404, 'Not found'); } } dispatch_put('/t1/:f1', 'update'); function update($f1) { $o = read_request_body('T1'); $real = new Test(); if($o->f1 == $f1 && $real->save($o)) { status(204); } else { halt(404, 'Not found'); } } dispatch_delete('/t1/:f1', 'delete'); function delete($f1) { $real = new Test(); if($real->delete($f1)) { status(204); } else { halt(404, 'Not found'); } } /////* NOTE: hack limonnade.php function request_methods by adding "OPTIONS" to array of valid methods. */ ////route('OPTIONS', '**', 'options', array()); ////function options() { //// header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"); //// header("Access-Control-Allow-Headers: Content-Type, Accept"); //// status(200); ////} run(); ?>