API: Fixes #69. Customisation of has|many_xxx relations

This commit is contained in:
Russell Michell 2019-06-28 11:49:26 +12:00 committed by Robbie Averill
parent e0f4e5684f
commit fb743bf9f1
2 changed files with 80 additions and 9 deletions

View File

@ -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

View File

@ -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;