Skip to content

Commit

Permalink
(merged from branches/roa. use "svn log -c <changeset> -g <module-svn…
Browse files Browse the repository at this point in the history
…-path>" for detailed commit message)

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@60206 467b73ca-7a2a-4603-9d3b-597d59a354a9
  • Loading branch information
chillu committed Aug 9, 2008
1 parent 03fcc80 commit 6bd5da7
Show file tree
Hide file tree
Showing 16 changed files with 413 additions and 252 deletions.
2 changes: 1 addition & 1 deletion _config.php
Expand Up @@ -19,7 +19,7 @@

// Default director
Director::addRules(10, array(
'Security' => 'Security',
'Security//$Action/$ID/$OtherID' => 'Security',
//'Security/$Action/$ID' => 'Security',
'db/$Action' => 'DatabaseAdmin',
'$Controller' => array(
Expand Down
66 changes: 46 additions & 20 deletions api/RestfulServer.php
Expand Up @@ -24,32 +24,37 @@
*
* - POST /api/v1/(ClassName)/(ID)/(MethodName) - executes a method on the given object (e.g, publish)
*
* @todo Finish RestfulServer_Item and RestfulServer_List implementation and re-enable $url_handlers
*
* @package sapphire
* @subpackage api
*/
class RestfulServer extends Controller {
static $url_handlers = array(
'$ClassName/#ID' => 'handleItem',
'$ClassName' => 'handleList',
'$ClassName/$ID/$Relation' => 'handleAction'
#'$ClassName/#ID' => 'handleItem',
#'$ClassName' => 'handleList',
);

protected static $api_base = "api/v1/";

function handleItem($params) {
return new RestfulServer_Item(DataObject::get_by_id($params["ClassName"], $params["ID"]));
/*
function handleItem($request) {
return new RestfulServer_Item(DataObject::get_by_id($request->param("ClassName"), $request->param("ID")));
}
function handleList($params) {
return new RestfulServer_List(DataObject::get($params["ClassName"],""));
function handleList($request) {
return new RestfulServer_List(DataObject::get($request->param("ClassName"),""));
}
*/

/**
* This handler acts as the switchboard for the controller.
* Since no $Action url-param is set, all requests are sent here.
*/
function index() {
ContentNegotiator::disable();

$requestMethod = $_SERVER['REQUEST_METHOD'];

if(!isset($this->urlParams['ClassName'])) return $this->notFound();
Expand Down Expand Up @@ -112,6 +117,12 @@ function index() {
*
* - 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
*
* @param String $className
* @param Int $id
* @param String $relation
* @param String $contentType
* @return String The serialized representation of the requested object(s) - usually XML or JSON.
*/
protected function getHandler($className, $id, $relation, $contentType) {
if($id) {
Expand Down Expand Up @@ -156,7 +167,11 @@ protected function getHandler($className, $id, $relation, $contentType) {
}

/**
* Generate an XML representation of the given DataObject.
* Generate an XML representation of the given {@link DataObject}.
*
* @param DataObject $obj
* @param $includeHeader Include <?xml ...?> header (Default: true)
* @return String XML
*/
protected function dataObjectAsXML(DataObject $obj, $includeHeader = true) {
$className = $obj->class;
Expand Down Expand Up @@ -212,22 +227,30 @@ protected function dataObjectAsXML(DataObject $obj, $includeHeader = true) {
}

/**
* Generate an XML representation of the given DataObject.
* Generate an XML representation of the given {@link DataObjectSet}.
*
* @param DataObjectSet $set
* @return String XML
*/
protected function dataObjectSetAsXML(DataObjectSet $set) {
$className = $set->class;

$json = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<$className>\n";
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<$className>\n";
foreach($set as $item) {
if($item->canView()) $json .= $this->dataObjectAsXML($item, false);
if($item->canView()) $xml .= $this->dataObjectAsXML($item, false);
}
$json .= "</$className>";
$xml .= "</$className>";

return $json;
return $xml;
}

/**
* Generate an XML representation of the given DataObject.
* Generate an JSON representation of the given {@link DataObject}.
*
* @see http://json.org
*
* @param DataObject $obj
* @return String JSON
*/
protected function dataObjectAsJSON(DataObject $obj) {
$className = $obj->class;
Expand Down Expand Up @@ -278,7 +301,10 @@ protected function dataObjectAsJSON(DataObject $obj) {
}

/**
* Generate an XML representation of the given DataObject.
* Generate an JSON representation of the given {@link DataObjectSet}.
*
* @param DataObjectSet $set
* @return String JSON
*/
protected function dataObjectSetAsJSON(DataObjectSet $set) {
$jsonParts = array();
Expand Down Expand Up @@ -346,8 +372,8 @@ function __construct($list) {
$this->list = $list;
}

function handleItem($params) {
return new RestulServer_Item($this->list->getById($params['ID']));
function handleItem($request) {
return new RestulServer_Item($this->list->getById($request->param('ID')));
}
}

Expand All @@ -363,11 +389,11 @@ function __construct($item) {
$this->item = $item;
}

function handleRelation($params) {
$funcName = $params['Relation'];
function handleRelation($request) {
$funcName = $request('Relation');
$relation = $this->item->$funcName();

if($relation instanceof DataObjectSet) return new RestfulServer_List($relation);
else return new RestfulServer_Item($relation)l
else return new RestfulServer_Item($relation);
}
}
10 changes: 5 additions & 5 deletions api/RestfulService.php
Expand Up @@ -284,11 +284,11 @@ function getValues($xml, $collection=NULL, $element=NULL){
$childElements = $xml->{$collection}->{$element};

if($childElements){
foreach($childElements as $child){
$data = array();
$this->getRecurseValues($child,$data);
$output->push(new ArrayData($data));
}
foreach($childElements as $child){
$data = array();
$this->getRecurseValues($child,$data);
$output->push(new ArrayData($data));
}
}
return $output;
}
Expand Down
2 changes: 1 addition & 1 deletion core/control/Controller.php
Expand Up @@ -39,7 +39,7 @@ class Controller extends RequestHandlingData {
* Default URL handlers - (Action)/(ID)/(OtherID)
*/
static $url_handlers = array(
'$Action/$ID/$OtherID' => 'handleAction',
'$Action//$ID/$OtherID' => 'handleAction',
);

static $allowed_actions = array(
Expand Down
37 changes: 35 additions & 2 deletions core/control/HTTPRequest.php
Expand Up @@ -8,7 +8,7 @@
* match() to get the information that they need out of the URL. This is generally handled by
* {@link RequestHandlingData::handleRequest()}.
*/
class HTTPRequest extends Object {
class HTTPRequest extends Object implements ArrayAccess {
/**
* The non-extension parts of the URL, separated by "/"
*/
Expand Down Expand Up @@ -52,6 +52,39 @@ function requestVar($name) {
if(isset($this->postVars[$name])) return $this->postVars[$name];
if(isset($this->getVars[$name])) return $this->getVars[$name];
}

/**
* Enables the existence of a key-value pair in the request to be checked using
* array syntax, so isset($request['title']) will check for $_POST['title'] and $_GET['title]
*
* @param unknown_type $offset
* @return boolean
*/
function offsetExists($offset) {
if(isset($this->postVars[$offset])) return true;
if(isset($this->getVars[$offset])) return true;
return false;
}

/**
* Access a request variable using array syntax. eg: $request['title'] instead of $request->postVar('title')
*
* @param unknown_type $offset
* @return unknown
*/
function offsetGet($offset) {
return $this->requestVar($offset);
}

/**
* @ignore
*/
function offsetSet($offset, $value) {}

/**
* @ignore
*/
function offsetUnset($offset) {}

/**
* Construct a HTTPRequest from a URL relative to the site root.
Expand Down Expand Up @@ -159,7 +192,7 @@ function match($pattern, $shiftOnSuccess = false) {
// Load the arguments that actually have a value into $this->allParams
// This ensures that previous values aren't overridden with blanks
foreach($arguments as $k => $v) {
if($v) $this->allParams[$k] = $v;
if($v || !isset($this->allParams[$k])) $this->allParams[$k] = $v;
}

return $arguments;
Expand Down
2 changes: 2 additions & 0 deletions core/control/RequestHandlingData.php
Expand Up @@ -69,7 +69,9 @@ class RequestHandlingData extends ViewableData {
*/
function handleRequest($request) {
foreach($this->stat('url_handlers') as $rule => $action) {
if(isset($_GET['debug_request'])) Debug::message("Testing '$rule' with '" . $request->remaining() . "' on $this->class");
if($params = $request->match($rule, true)) {
if(isset($_GET['debug_request'])) Debug::message("Rule '$rule' matched on $this->class");

// Actions can reference URL parameters, eg, '$Action/$ID/$OtherID' => '$Action',
if($action[0] == '$') $action = $params[substr($action,1)];
Expand Down
21 changes: 8 additions & 13 deletions core/control/RootURLController.php
Expand Up @@ -7,23 +7,18 @@
*/
class RootURLController extends Controller {
protected static $is_at_root = false;

public function run($requestParams) {
public function handleRequest($request) {
self::$is_at_root = true;

$this->pushCurrent();
$controller = new ModelAsController();
$controller->setUrlParams(array(
'URLSegment' => self::get_homepage_urlsegment(),
'Action' => '',
));

$result = $controller->run($requestParams);
$controller = new ModelAsController();

$this->popCurrent();
return $result;
$request = new HTTPRequest("GET", self::get_homepage_urlsegment().'/', $request->getVars(), $request->postVars());
$request->match('$URLSegment//$Action');

return $controller->handleRequest($request);
}

/**
* Return the URL segment for the current HTTP_HOST value
*/
Expand Down
1 change: 1 addition & 0 deletions core/model/DataObject.php
Expand Up @@ -616,6 +616,7 @@ public function write($showDebug = false, $forceInsert = false, $forceWrite = fa
foreach($this->record as $fieldName => $fieldValue) {
if(isset($this->changed[$fieldName]) && $this->changed[$fieldName] && $fieldType = $classSingleton->fieldExists($fieldName)) {
$fieldObj = $this->obj($fieldName);
$fieldObj->setValue($this->record[$fieldName], $this->record);
if(!isset($manipulation[$class])) $manipulation[$class] = array();
if($fieldObj) $fieldObj->writeToManipulation($manipulation[$class]);
}
Expand Down

0 comments on commit 6bd5da7

Please sign in to comment.