Merge 07ddd20399
into a6f2162564
This commit is contained in:
commit
f11d470abd
71
README.md
71
README.md
|
@ -8,8 +8,8 @@
|
|||
## Overview
|
||||
|
||||
This class gives your application a RESTful API. All you have to do is set the `api_access` configuration option to `true`
|
||||
on the appropriate DataObjects. You will need to ensure that all of your data manipulation and security is defined in
|
||||
your model layer (ie, the DataObject classes) and not in your Controllers. This is the recommended design for SilverStripe
|
||||
on the appropriate `DataObject`. You will need to ensure that all of your data manipulation and security is defined in
|
||||
your model layer (ie, the `DataObject` classes) and not in your Controllers. This is the recommended design for SilverStripe
|
||||
applications.
|
||||
|
||||
## Requirements
|
||||
|
@ -20,7 +20,7 @@ For a SilverStripe 3.x compatible version of this module, please see the [1.0 br
|
|||
|
||||
## Configuration
|
||||
|
||||
Example DataObject with simple API access, giving full access to all object properties and relations,
|
||||
Example `DataObject` with simple API access, giving full access to all object properties and relations,
|
||||
unless explicitly controlled through model permissions.
|
||||
|
||||
```php
|
||||
|
@ -39,7 +39,7 @@ class Article extends DataObject {
|
|||
}
|
||||
```
|
||||
|
||||
Example DataObject with advanced API access, limiting viewing and editing to Title attribute only:
|
||||
Example `DataObject` with advanced API access, limiting viewing and editing to the "Title" attribute only:
|
||||
|
||||
```php
|
||||
namespace Vendor\Project;
|
||||
|
@ -60,7 +60,7 @@ class Article extends DataObject {
|
|||
}
|
||||
```
|
||||
|
||||
Example DataObject field mapping, allows aliasing fields so that public requests and responses display different field names:
|
||||
Example `DataObject` field mapping, allows aliasing fields so that public requests and responses display different field names:
|
||||
|
||||
```php
|
||||
namespace Vendor\Project;
|
||||
|
@ -83,7 +83,66 @@ class Article extends DataObject {
|
|||
];
|
||||
}
|
||||
```
|
||||
Given a dataobject with values:
|
||||
|
||||
Example `DataObject` `HasMany` and `ManyMany` field-display handling. Only available on `JSONDataFormatter`. Declaring a `getApiFields` method in your `DataObject` (or an `Extension` subclass) allows additional fields to be shown on those relations, in addition to "id", "className" and "href":
|
||||
|
||||
```php
|
||||
namespace Vendor\Project;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class Article extends DataObject {
|
||||
|
||||
private static $db = [
|
||||
'Title'=>'Text',
|
||||
'Published'=>'Boolean'
|
||||
];
|
||||
|
||||
private static $api_access = true;
|
||||
|
||||
/**
|
||||
* @param array $baseFields
|
||||
* @return array
|
||||
*/
|
||||
public function getApiFields($baseFields)
|
||||
{
|
||||
return [
|
||||
'Title' => $this->Title,
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Example `DataObject` `HasMany` and `ManyMany` field-display handling. Only available on `JSONDataFormatter`. Declaring a `getApiFields` method in your `DataObject` (or an `Extension` subclass) allows existing fields that the formatter returns (like "id", "className" and "href"), to be overloaded:
|
||||
|
||||
```php
|
||||
namespace Vendor\Project;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class Article extends DataObject {
|
||||
|
||||
private static $db = [
|
||||
'Title'=>'Text',
|
||||
'Published'=>'Boolean'
|
||||
];
|
||||
|
||||
private static $api_access = true;
|
||||
|
||||
/**
|
||||
* @param array $baseFields
|
||||
* @return array
|
||||
*/
|
||||
public function getApiFields($baseFields)
|
||||
{
|
||||
return [
|
||||
'href' => $this->myHrefOverrideMethod($baseFields['href']),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Given a `DataObject` with values:
|
||||
```yml
|
||||
ID: 12
|
||||
Title: Title Value
|
||||
|
|
|
@ -10,6 +10,8 @@ use SilverStripe\ORM\DataObjectInterface;
|
|||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\ORM\SS_List;
|
||||
use SilverStripe\ORM\FieldType;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
/**
|
||||
* Formats a DataObject's member fields into a JSON string
|
||||
|
@ -118,10 +120,16 @@ class JSONDataFormatter extends DataFormatter
|
|||
? $this->sanitiseClassName($relClass) . '/' . $obj->$fieldName
|
||||
: $this->sanitiseClassName($className) . "/$id/$relName";
|
||||
$href = Director::absoluteURL($rel);
|
||||
$serobj->$relName = ArrayData::array_to_object(array(
|
||||
$component = $obj->getField($relName);
|
||||
$baseFields = [
|
||||
"className" => $relClass,
|
||||
"href" => "$href.json",
|
||||
"id" => self::cast($obj->obj($fieldName))
|
||||
"id" => self::cast($obj->obj($fieldName)),
|
||||
];
|
||||
|
||||
$serobj->$relName = ArrayData::array_to_object(array_replace(
|
||||
$baseFields,
|
||||
ClassInfo::hasMethod($component, 'getApiFields') ? (array) $component->getApiFields($baseFields) : []
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -152,10 +160,14 @@ class JSONDataFormatter extends DataFormatter
|
|||
}
|
||||
$rel = $this->config()->api_base . $this->sanitiseClassName($relClass) . "/$item->ID";
|
||||
$href = Director::absoluteURL($rel);
|
||||
$innerParts[] = ArrayData::array_to_object(array(
|
||||
$baseFields = [
|
||||
"className" => $relClass,
|
||||
"href" => "$href.json",
|
||||
"id" => $item->ID
|
||||
];
|
||||
$innerParts[] = ArrayData::array_to_object(array_replace(
|
||||
$baseFields,
|
||||
ClassInfo::hasMethod($item, 'getApiFields') ? (array) $item->getApiFields($baseFields) : []
|
||||
));
|
||||
}
|
||||
$serobj->$relName = $innerParts;
|
||||
|
|
|
@ -3,16 +3,15 @@
|
|||
namespace SilverStripe\RestfulServer\Tests;
|
||||
|
||||
use SilverStripe\RestfulServer\RestfulServer;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\RestfulServer\Tests\Stubs\JSONDataFormatterTypeTestObject;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\RestfulServer\DataFormatter\JSONDataFormatter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @todo Test Relation getters
|
||||
* @todo Test filter and limit through GET params
|
||||
* @todo Test DELETE verb
|
||||
*
|
||||
* Tests improvements made to JsonTypes,
|
||||
* calls method which appends more fields
|
||||
*/
|
||||
class JSONDataFormatterTest extends SapphireTest
|
||||
{
|
||||
|
@ -22,11 +21,20 @@ class JSONDataFormatterTest extends SapphireTest
|
|||
JSONDataFormatterTypeTestObject::class,
|
||||
];
|
||||
|
||||
protected $usesDatabase = true;
|
||||
|
||||
public function testJSONTypes()
|
||||
{
|
||||
|
||||
// Needed as private static $api_access = true; doesn't seem to work on the stub file
|
||||
Config::inst()->update(JSONDataFormatterTypeTestObject::class, 'api_access', true);
|
||||
|
||||
// Grab test object
|
||||
$formatter = new JSONDataFormatter();
|
||||
|
||||
$parent = $this->objFromFixture(JSONDataFormatterTypeTestObject::class, 'parent');
|
||||
$json = $formatter->convertDataObject($parent);
|
||||
|
||||
$this->assertRegexp('/"ID":\d+/', $json, 'PK casted to integer');
|
||||
$this->assertRegexp('/"Created":"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}"/', $json, 'Datetime casted to string');
|
||||
$this->assertContains('"Name":"Parent"', $json, 'String casted to string');
|
||||
|
@ -37,10 +45,35 @@ class JSONDataFormatterTest extends SapphireTest
|
|||
|
||||
$child3 = $this->objFromFixture(JSONDataFormatterTypeTestObject::class, 'child3');
|
||||
$json = $formatter->convertDataObject($child3);
|
||||
|
||||
$this->assertContains('"Name":null', $json, 'Empty string is null');
|
||||
$this->assertContains('"Active":false', $json, 'Empty boolean is false');
|
||||
$this->assertContains('"Sort":0', $json, 'Empty integer is 0');
|
||||
$this->assertContains('"Average":0', $json, 'Empty float is 0');
|
||||
$this->assertRegexp('/"ParentID":\d+/', $json, 'FK casted to integer');
|
||||
|
||||
$original = $this->objFromFixture(JSONDataFormatterTypeTestObject::class, 'original');
|
||||
$json = json_decode($formatter->convertDataObject($original));
|
||||
|
||||
// Returns valid array and isn't null
|
||||
$this->assertNotEmpty($json, 'Array is empty');
|
||||
|
||||
// Test that original fields still exist, ie id, href, and className
|
||||
$standard_id = $json->Children[0]->id;
|
||||
$standard_className = $json->Children[0]->className;
|
||||
$standard_href = $json->Children[0]->href;
|
||||
|
||||
$this->assertEquals(8, $standard_id, "Standard id field not equal");
|
||||
$this->assertEquals('SilverStripe\RestfulServer\Tests\Stubs\JSONDataFormatterTypeTestObject', $standard_className, "Standard className does not equal");
|
||||
$this->assertEquals('http://localhost/api/v1/SilverStripe-RestfulServer-Tests-Stubs-JSONDataFormatterTypeTestObject/8.json', $standard_href, "Standard href field not equal");
|
||||
|
||||
// Test method improvements, more fields rather than just id, href, className
|
||||
$this->assertEquals(9, $json->ID, "ID not equal");
|
||||
$this->assertEquals("SilverStripe\\RestfulServer\\Tests\\Stubs\\JSONDataFormatterTypeTestObject", $json->ClassName, "Class not equal");
|
||||
$this->assertEquals("Test Object", $json->Name, "Name not equal");
|
||||
$this->assertEquals(false, $json->Active, "Active not equal to false");
|
||||
$this->assertEquals(0, $json->Sort, "Sort not equal to 0");
|
||||
$this->assertEquals(0, $json->Average, "Average not equal to 0");
|
||||
$this->assertEquals(0, $json->ParentID, "ParentID not equal to 0");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
SilverStripe\RestfulServer\Tests\Stubs\JSONDataFormatterTypeTestObject:
|
||||
foo:
|
||||
ID: 8
|
||||
Name: Test Object 1
|
||||
original:
|
||||
ID: 9
|
||||
Name: Test Object
|
||||
Children: =>SilverStripe\RestfulServer\Tests\Stubs\JSONDataFormatterTypeTestObject.foo
|
||||
parent:
|
||||
Name: Parent
|
||||
Active: true
|
||||
|
|
Loading…
Reference in New Issue