urlParams['ClassName']; $id = $this->urlParams['ID']; switch($requestMethod) { case 'GET': return $this->getHandler($className, $id); case 'PUT': return $this->putHandler($className, $id); case 'DELETE': return $this->deleteHandler($className, $id); case 'POST': } } /** * Handler for object read. * * The data object will be returned in the following format: * * * Value * ... * * ... * * * * * ... * * * * * * * Access is controlled by two variables: * * - static $api_access must be set. This enables the API on a class by class basis * - $obj->canView() must return true. This lets you implement record-level security */ protected function getHandler($className, $id) { $obj = DataObject::get_by_id($className, $id); if(!$obj) { return $this->notFound(); } // TO DO - inspect that Accept header as well. $_GET['accept'] can still be checked, as it's handy for debugging $contentType = isset($_GET['accept']) ? $_GET['accept'] : 'text/xml'; if($obj->stat('api_access') && $obj->canView()) { switch($contentType) { case "text/xml": $this->getResponse()->addHeader("Content-type", "text/xml"); return $this->dataObjectAsXML($obj); case "text/json": $this->getResponse()->addHeader("Content-type", "text/json"); return $this->dataObjectAsJSON($obj); case "text/html": case "application/xhtml+xml": $this->getResponse()->addHeader("Content-type", "text/json"); return $this->dataObjectAsXHTML($obj); } } else { return $this->permissionFailure(); } } /** * Generate an XML representation of the given DataObject. */ protected function dataObjectAsXML(DataObject $obj) { $className = $obj->class; $id = $obj->ID; $json = "\n<$className>\n"; foreach($obj->db() as $fieldName => $fieldType) { $json .= "<$fieldName>" . Convert::raw2xml($obj->$fieldName) . "\n"; } foreach($obj->has_one() as $relName => $relClass) { $fieldName = $relName . 'ID'; if($obj->$fieldName) { $href = Director::absoluteURL(self::$api_base . "$relClass/" . $obj->$fieldName); } else { $href = Director::absoluteURL(self::$api_base . "$className/$id/$relName"); } $json .= "<$relName linktype=\"has_one\" href=\"$href\" id=\"{$obj->$fieldName}\" />\n"; } foreach($obj->has_many() as $relName => $relClass) { $json .= "<$relName linktype=\"has_many\">\n"; $items = $obj->$relName(); foreach($items as $item) { //$href = Director::absoluteURL(self::$api_base . "$className/$id/$relName/$item->ID"); $href = Director::absoluteURL(self::$api_base . "$relClass/$item->ID"); $json .= "<$relClass href=\"$href\" id=\"{$item->ID}\" />\n"; } $json .= "\n"; } foreach($obj->many_many() as $relName => $relClass) { $json .= "<$relName linktype=\"many_many\">\n"; $items = $obj->$relName(); foreach($items as $item) { //$href = Director::absoluteURL(self::$api_base . "$className/$id/$relName/$item->ID"); $href = Director::absoluteURL(self::$api_base . "$relClass/$item->ID"); $json .= "<$relClass href=\"$href\" id=\"{$item->ID}\" />\n"; } $json .= "\n"; } $json .= ""; return $json; } /** * Generate an XML representation of the given DataObject. */ protected function dataObjectAsJSON(DataObject $obj) { $className = $obj->class; $id = $obj->ID; $json = "{\n className : \"$className\",\n"; foreach($obj->db() as $fieldName => $fieldType) { $jsonParts[] = "$fieldName : \"" . Convert::raw2js($obj->$fieldName) . "\""; } foreach($obj->has_one() as $relName => $relClass) { $fieldName = $relName . 'ID'; if($obj->$fieldName) { $href = Director::absoluteURL(self::$api_base . "$relClass/" . $obj->$fieldName); } else { $href = Director::absoluteURL(self::$api_base . "$className/$id/$relName"); } $jsonParts[] = "$relName : { className : \"$relClass\", href : \"$href\", id : \"{$obj->$fieldName}\" }"; } foreach($obj->has_many() as $relName => $relClass) { $jsonInnerParts = array(); $items = $obj->$relName(); foreach($items as $item) { //$href = Director::absoluteURL(self::$api_base . "$className/$id/$relName/$item->ID"); $href = Director::absoluteURL(self::$api_base . "$relClass/$item->ID"); $jsonInnerParts[] = "{ className : \"$relClass\", href : \"$href\", id : \"{$obj->$fieldName}\" }"; } $jsonParts[] = "$relName : [\n " . implode(",\n ", $jsonInnerParts) . " \n ]"; } foreach($obj->many_many() as $relName => $relClass) { $jsonInnerParts = array(); $items = $obj->$relName(); foreach($items as $item) { //$href = Director::absoluteURL(self::$api_base . "$className/$id/$relName/$item->ID"); $href = Director::absoluteURL(self::$api_base . "$relClass/$item->ID"); $jsonInnerParts[] = " { className : \"$relClass\", href : \"$href\", id : \"{$obj->$fieldName}\" }"; } $jsonParts[] = "$relName : [\n " . implode(",\n ", $jsonInnerParts) . "\n ]"; } return "{\n " . implode(",\n ", $jsonParts) . "\n}"; } /** * Handler for object delete */ protected function deleteHandler($className, $id) { if($id) { $obj = DataObject::get_by_id($className, $id); if($obj->stat('api_access') && $obj->canDelete()) { $obj->delete(); } else { return $this->permissionFailure(); } } } /** * Handler for object write */ protected function putHandler($className, $id) { return $this->permissionFailure(); } /** * Handler for object append / method call */ protected function postHandler($className, $id) { return $this->permissionFailure(); } protected function permissionFailure() { // return a 401 $this->getResponse()->setStatusCode(403); return "You don't have access to this item through the API."; } protected function notFound() { // return a 404 $this->getResponse()->setStatusCode(404); return "That object wasn't found"; } }