Merge branch '1.0'

This commit is contained in:
Robbie Averill 2017-11-17 14:59:38 +13:00
commit e5a757d589
4 changed files with 190 additions and 157 deletions

View File

@ -4,22 +4,16 @@ sudo: false
language: php
php:
- 5.3
- 5.4
- 5.5
env:
- DB=MYSQL CORE_RELEASE=3.5
matrix:
include:
- php: 5.4
env: DB=MYSQL CORE_RELEASE=3.3
- php: 5.5
env: DB=MYSQL CORE_RELEASE=3.4
- php: 5.6
env: DB=PGSQL CORE_RELEASE=3.5
- php: 7.0
env: DB=MYSQL CORE_RELEASE=3
- php: 5.6
env: DB=MYSQL CORE_RELEASE=3.1
- php: 5.6
env: DB=PGSQL CORE_RELEASE=3.2
- php: 7.1
env: DB=MYSQL CORE_RELEASE=3.6

View File

@ -204,7 +204,7 @@ class RestfulServer extends Controller
if (!$obj) {
return $this->notFound();
}
if (!$obj->canView()) {
if (!$obj->canView($this->getMember())) {
return $this->permissionFailure();
}
@ -229,20 +229,22 @@ class RestfulServer extends Controller
$fields = $rawFields ? explode(',', $rawFields) : null;
if ($obj instanceof SS_List) {
$responseFormatter->setTotalSize($obj->dataQuery()->query()->unlimitedRowCount());
$objs = new ArrayList($obj->toArray());
$objs = ArrayList::create($obj->toArray());
foreach ($objs as $obj) {
if (!$obj->canView()) {
if (!$obj->canView($this->getMember())) {
$objs->remove($obj);
}
}
$responseFormatter->setTotalSize($objs->count());
return $responseFormatter->convertDataObjectSet($objs, $fields);
} elseif (!$obj) {
}
if (!$obj) {
$responseFormatter->setTotalSize(0);
return $responseFormatter->convertDataObjectSet(new ArrayList(), $fields);
} else {
return $responseFormatter->convertDataObject($obj, $fields);
}
return $responseFormatter->convertDataObject($obj, $fields);
}
/**
@ -372,7 +374,7 @@ class RestfulServer extends Controller
if (!$obj) {
return $this->notFound();
}
if (!$obj->canDelete()) {
if (!$obj->canDelete($this->getMember())) {
return $this->permissionFailure();
}
@ -391,7 +393,7 @@ class RestfulServer extends Controller
if (!$obj) {
return $this->notFound();
}
if (!$obj->canEdit()) {
if (!$obj->canEdit($this->getMember())) {
return $this->permissionFailure();
}
@ -405,7 +407,11 @@ class RestfulServer extends Controller
return $this->unsupportedMediaType();
}
/** @var DataObject|string */
$obj = $this->updateDataObject($obj, $reqFormatter);
if (is_string($obj)) {
return $obj;
}
$this->getResponse()->setStatusCode(200); // Success
$this->getResponse()->addHeader('Content-Type', $responseFormatter->getOutputContentType());
@ -456,37 +462,41 @@ class RestfulServer extends Controller
$this->getResponse()->setStatusCode(204); // No Content
return true;
} else {
if (!singleton($className)->canCreate()) {
return $this->permissionFailure();
}
$obj = new $className();
$reqFormatter = $this->getRequestDataFormatter($className);
if (!$reqFormatter) {
return $this->unsupportedMediaType();
}
$responseFormatter = $this->getResponseDataFormatter($className);
$obj = $this->updateDataObject($obj, $reqFormatter);
$this->getResponse()->setStatusCode(201); // Created
$this->getResponse()->addHeader('Content-Type', $responseFormatter->getOutputContentType());
// Append the default extension for the output format to the Location header
// or else we'll use the default (XML)
$types = $responseFormatter->supportedExtensions();
$type = '';
if (count($types)) {
$type = ".{$types[0]}";
}
$objHref = Director::absoluteURL(self::$api_base . "$obj->class/$obj->ID" . $type);
$this->getResponse()->addHeader('Location', $objHref);
return $responseFormatter->convertDataObject($obj);
}
if (!singleton($className)->canCreate($this->getMember())) {
return $this->permissionFailure();
}
$obj = new $className();
$reqFormatter = $this->getRequestDataFormatter($className);
if (!$reqFormatter) {
return $this->unsupportedMediaType();
}
$responseFormatter = $this->getResponseDataFormatter($className);
/** @var DataObject|string $obj */
$obj = $this->updateDataObject($obj, $reqFormatter);
if (is_string($obj)) {
return $obj;
}
$this->getResponse()->setStatusCode(201); // Created
$this->getResponse()->addHeader('Content-Type', $responseFormatter->getOutputContentType());
// Append the default extension for the output format to the Location header
// or else we'll use the default (XML)
$types = $responseFormatter->supportedExtensions();
$type = '';
if (count($types)) {
$type = ".{$types[0]}";
}
$objHref = Director::absoluteURL(self::$api_base . "$obj->class/$obj->ID" . $type);
$this->getResponse()->addHeader('Location', $objHref);
return $responseFormatter->convertDataObject($obj);
}
/**
@ -498,7 +508,7 @@ class RestfulServer extends Controller
*
* @param DataObject $obj
* @param DataFormatter $formatter
* @return DataObject The passed object
* @return DataObject|string The passed object, or "No Content" if incomplete input data is provided
*/
protected function updateDataObject($obj, $formatter)
{
@ -649,6 +659,16 @@ class RestfulServer extends Controller
}
return $allowedRelations;
}
/**
* Get the current Member, if available
*
* @return Member|null
*/
protected function getMember()
{
return Member::currentUser();
}
}
/**

View File

@ -1,28 +1,29 @@
{
"name": "silverstripe/restfulserver",
"description": "Add a RESTful API to your SilverStripe application",
"type": "silverstripe-module",
"keywords": ["silverstripe", "rest", "api"],
"authors": [
{
"name": "Hamish Friedlander",
"email": "hamish@silverstripe.com"
},
{
"name": "Sam Minnee",
"email": "sam@silverstripe.com"
}
],
"require":
{
"silverstripe/framework": "3.*"
},
"extra":
{
"branch-alias":
{
"dev-master": "1.0.x-dev"
}
},
"license": "BSD-3-Clause"
"name": "silverstripe/restfulserver",
"description": "Add a RESTful API to your SilverStripe application",
"type": "silverstripe-module",
"keywords": [
"silverstripe",
"rest",
"api"
],
"authors": [
{
"name": "Hamish Friedlander",
"email": "hamish@silverstripe.com"
},
{
"name": "Sam Minnee",
"email": "sam@silverstripe.com"
}
],
"require": {
"silverstripe/framework": "3.*"
},
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"license": "BSD-3-Clause"
}

View File

@ -193,6 +193,19 @@ class RestfulServerTest extends SapphireTest
unset($_SERVER['PHP_AUTH_PW']);
}
public function testPostWithoutBodyReturnsNoContent()
{
$_SERVER['PHP_AUTH_USER'] = 'editor@test.com';
$_SERVER['PHP_AUTH_PW'] = 'editor';
$url = '/api/v1/RestfulServerTest_Comment';
$response = Director::test($url, null, null, 'POST');
$this->assertEquals('No Content', $response->getBody());
unset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
}
public function testPUTwithJSON()
{
$comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1');
@ -463,6 +476,8 @@ class RestfulServerTest extends SapphireTest
$response = Director::test($url, null, null, 'GET');
$this->assertEquals($response->getStatusCode(), 200);
$this->assertNotContains('Unspeakable', $response->getBody());
$responseArray = Convert::json2array($response->getBody());
$this->assertSame(0, $responseArray['totalSize']);
// With authentication
$_SERVER['PHP_AUTH_USER'] = 'editor@test.com';
@ -471,6 +486,9 @@ class RestfulServerTest extends SapphireTest
$response = Director::test($url, null, null, 'GET');
$this->assertEquals($response->getStatusCode(), 200);
$this->assertContains('Unspeakable', $response->getBody());
// Assumption: default formatter is XML
$responseArray = Convert::xml2array($response->getBody());
$this->assertEquals(1, $responseArray['@attributes']['totalSize']);
unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']);
}