Merge branch '1.0'
This commit is contained in:
commit
e5a757d589
18
.travis.yml
18
.travis.yml
|
@ -4,22 +4,16 @@ sudo: false
|
||||||
|
|
||||||
language: php
|
language: php
|
||||||
|
|
||||||
php:
|
|
||||||
- 5.3
|
|
||||||
- 5.4
|
|
||||||
- 5.5
|
|
||||||
|
|
||||||
env:
|
|
||||||
- DB=MYSQL CORE_RELEASE=3.5
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
- php: 5.4
|
||||||
|
env: DB=MYSQL CORE_RELEASE=3.3
|
||||||
|
- php: 5.5
|
||||||
|
env: DB=MYSQL CORE_RELEASE=3.4
|
||||||
- php: 5.6
|
- php: 5.6
|
||||||
|
env: DB=PGSQL CORE_RELEASE=3.5
|
||||||
|
- php: 7.0
|
||||||
env: DB=MYSQL CORE_RELEASE=3
|
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
|
- php: 7.1
|
||||||
env: DB=MYSQL CORE_RELEASE=3.6
|
env: DB=MYSQL CORE_RELEASE=3.6
|
||||||
|
|
||||||
|
|
|
@ -204,7 +204,7 @@ class RestfulServer extends Controller
|
||||||
if (!$obj) {
|
if (!$obj) {
|
||||||
return $this->notFound();
|
return $this->notFound();
|
||||||
}
|
}
|
||||||
if (!$obj->canView()) {
|
if (!$obj->canView($this->getMember())) {
|
||||||
return $this->permissionFailure();
|
return $this->permissionFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,20 +229,22 @@ class RestfulServer extends Controller
|
||||||
$fields = $rawFields ? explode(',', $rawFields) : null;
|
$fields = $rawFields ? explode(',', $rawFields) : null;
|
||||||
|
|
||||||
if ($obj instanceof SS_List) {
|
if ($obj instanceof SS_List) {
|
||||||
$responseFormatter->setTotalSize($obj->dataQuery()->query()->unlimitedRowCount());
|
$objs = ArrayList::create($obj->toArray());
|
||||||
$objs = new ArrayList($obj->toArray());
|
|
||||||
foreach ($objs as $obj) {
|
foreach ($objs as $obj) {
|
||||||
if (!$obj->canView()) {
|
if (!$obj->canView($this->getMember())) {
|
||||||
$objs->remove($obj);
|
$objs->remove($obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$responseFormatter->setTotalSize($objs->count());
|
||||||
return $responseFormatter->convertDataObjectSet($objs, $fields);
|
return $responseFormatter->convertDataObjectSet($objs, $fields);
|
||||||
} elseif (!$obj) {
|
}
|
||||||
|
|
||||||
|
if (!$obj) {
|
||||||
$responseFormatter->setTotalSize(0);
|
$responseFormatter->setTotalSize(0);
|
||||||
return $responseFormatter->convertDataObjectSet(new ArrayList(), $fields);
|
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) {
|
if (!$obj) {
|
||||||
return $this->notFound();
|
return $this->notFound();
|
||||||
}
|
}
|
||||||
if (!$obj->canDelete()) {
|
if (!$obj->canDelete($this->getMember())) {
|
||||||
return $this->permissionFailure();
|
return $this->permissionFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +393,7 @@ class RestfulServer extends Controller
|
||||||
if (!$obj) {
|
if (!$obj) {
|
||||||
return $this->notFound();
|
return $this->notFound();
|
||||||
}
|
}
|
||||||
if (!$obj->canEdit()) {
|
if (!$obj->canEdit($this->getMember())) {
|
||||||
return $this->permissionFailure();
|
return $this->permissionFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +407,11 @@ class RestfulServer extends Controller
|
||||||
return $this->unsupportedMediaType();
|
return $this->unsupportedMediaType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var DataObject|string */
|
||||||
$obj = $this->updateDataObject($obj, $reqFormatter);
|
$obj = $this->updateDataObject($obj, $reqFormatter);
|
||||||
|
if (is_string($obj)) {
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
|
||||||
$this->getResponse()->setStatusCode(200); // Success
|
$this->getResponse()->setStatusCode(200); // Success
|
||||||
$this->getResponse()->addHeader('Content-Type', $responseFormatter->getOutputContentType());
|
$this->getResponse()->addHeader('Content-Type', $responseFormatter->getOutputContentType());
|
||||||
|
@ -456,37 +462,41 @@ class RestfulServer extends Controller
|
||||||
|
|
||||||
$this->getResponse()->setStatusCode(204); // No Content
|
$this->getResponse()->setStatusCode(204); // No Content
|
||||||
return true;
|
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 DataObject $obj
|
||||||
* @param DataFormatter $formatter
|
* @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)
|
protected function updateDataObject($obj, $formatter)
|
||||||
{
|
{
|
||||||
|
@ -649,6 +659,16 @@ class RestfulServer extends Controller
|
||||||
}
|
}
|
||||||
return $allowedRelations;
|
return $allowedRelations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current Member, if available
|
||||||
|
*
|
||||||
|
* @return Member|null
|
||||||
|
*/
|
||||||
|
protected function getMember()
|
||||||
|
{
|
||||||
|
return Member::currentUser();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,28 +1,29 @@
|
||||||
{
|
{
|
||||||
"name": "silverstripe/restfulserver",
|
"name": "silverstripe/restfulserver",
|
||||||
"description": "Add a RESTful API to your SilverStripe application",
|
"description": "Add a RESTful API to your SilverStripe application",
|
||||||
"type": "silverstripe-module",
|
"type": "silverstripe-module",
|
||||||
"keywords": ["silverstripe", "rest", "api"],
|
"keywords": [
|
||||||
"authors": [
|
"silverstripe",
|
||||||
{
|
"rest",
|
||||||
"name": "Hamish Friedlander",
|
"api"
|
||||||
"email": "hamish@silverstripe.com"
|
],
|
||||||
},
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Sam Minnee",
|
"name": "Hamish Friedlander",
|
||||||
"email": "sam@silverstripe.com"
|
"email": "hamish@silverstripe.com"
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
"require":
|
"name": "Sam Minnee",
|
||||||
{
|
"email": "sam@silverstripe.com"
|
||||||
"silverstripe/framework": "3.*"
|
}
|
||||||
},
|
],
|
||||||
"extra":
|
"require": {
|
||||||
{
|
"silverstripe/framework": "3.*"
|
||||||
"branch-alias":
|
},
|
||||||
{
|
"extra": {
|
||||||
"dev-master": "1.0.x-dev"
|
"branch-alias": {
|
||||||
}
|
"dev-master": "1.1.x-dev"
|
||||||
},
|
}
|
||||||
"license": "BSD-3-Clause"
|
},
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,6 +193,19 @@ class RestfulServerTest extends SapphireTest
|
||||||
unset($_SERVER['PHP_AUTH_PW']);
|
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()
|
public function testPUTwithJSON()
|
||||||
{
|
{
|
||||||
$comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1');
|
$comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1');
|
||||||
|
@ -463,6 +476,8 @@ class RestfulServerTest extends SapphireTest
|
||||||
$response = Director::test($url, null, null, 'GET');
|
$response = Director::test($url, null, null, 'GET');
|
||||||
$this->assertEquals($response->getStatusCode(), 200);
|
$this->assertEquals($response->getStatusCode(), 200);
|
||||||
$this->assertNotContains('Unspeakable', $response->getBody());
|
$this->assertNotContains('Unspeakable', $response->getBody());
|
||||||
|
$responseArray = Convert::json2array($response->getBody());
|
||||||
|
$this->assertSame(0, $responseArray['totalSize']);
|
||||||
|
|
||||||
// With authentication
|
// With authentication
|
||||||
$_SERVER['PHP_AUTH_USER'] = 'editor@test.com';
|
$_SERVER['PHP_AUTH_USER'] = 'editor@test.com';
|
||||||
|
@ -471,6 +486,9 @@ class RestfulServerTest extends SapphireTest
|
||||||
$response = Director::test($url, null, null, 'GET');
|
$response = Director::test($url, null, null, 'GET');
|
||||||
$this->assertEquals($response->getStatusCode(), 200);
|
$this->assertEquals($response->getStatusCode(), 200);
|
||||||
$this->assertContains('Unspeakable', $response->getBody());
|
$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_USER']);
|
||||||
unset($_SERVER['PHP_AUTH_PW']);
|
unset($_SERVER['PHP_AUTH_PW']);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue