silverstripe-framework/api/JSONDataFormatter.php

162 lines
4.7 KiB
PHP

<?php
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\ORM\SS_List;
/**
* @package framework
* @subpackage formatters
*/
class JSONDataFormatter extends DataFormatter {
/**
* @config
* @todo pass this from the API to the data formatter somehow
*/
private static $api_base = "api/v1/";
protected $outputContentType = 'application/json';
public function supportedExtensions() {
return array(
'json',
'js'
);
}
public function supportedMimeTypes() {
return array(
'application/json',
'text/x-json'
);
}
/**
* Generate a JSON representation of the given {@link DataObject}.
*
* @param DataObjectInterface $obj The object
* @param array $fields If supplied, only fields in the list will be returned
* @param array $relations Not used
* @return String JSON
*/
public function convertDataObject(DataObjectInterface $obj, $fields = null, $relations = null) {
return Convert::raw2json($this->convertDataObjectToJSONObject($obj, $fields, $relations));
}
/**
* Internal function to do the conversion of a single data object. It builds an empty object and dynamically
* adds the properties it needs to it. If it's done as a nested array, json_encode or equivalent won't use
* JSON object notation { ... }.
* @param DataObjectInterface|DataObject $obj
* @param array $fields
* @param array $relations
* @return stdClass
*/
public function convertDataObjectToJSONObject(DataObjectInterface $obj, $fields = null, $relations = null) {
$className = $obj->class;
$id = $obj->ID;
$serobj = ArrayData::array_to_object();
foreach($this->getFieldsForObj($obj) as $fieldName => $fieldType) {
// Field filtering
if($fields && !in_array($fieldName, $fields)) continue;
$fieldValue = $obj->obj($fieldName)->forTemplate();
$serobj->$fieldName = $fieldValue;
}
if($this->relationDepth > 0) {
foreach($obj->hasOne() as $relName => $relClass) {
if(!singleton($relClass)->stat('api_access')) continue;
// Field filtering
if($fields && !in_array($relName, $fields)) continue;
if($this->customRelations && !in_array($relName, $this->customRelations)) continue;
$fieldName = $relName . 'ID';
if($obj->$fieldName) {
$href = Director::absoluteURL($this->config()->api_base . "$relClass/" . $obj->$fieldName);
} else {
$href = Director::absoluteURL($this->config()->api_base . "$className/$id/$relName");
}
$serobj->$relName = ArrayData::array_to_object(array(
"className" => $relClass,
"href" => "$href.json",
"id" => $obj->$fieldName
));
}
foreach($obj->hasMany() as $relName => $relClass) {
if(!singleton($relClass)->stat('api_access')) continue;
// Field filtering
if($fields && !in_array($relName, $fields)) continue;
if($this->customRelations && !in_array($relName, $this->customRelations)) continue;
$innerParts = array();
$items = $obj->$relName();
foreach($items as $item) {
//$href = Director::absoluteURL($this->config()->api_base . "$className/$id/$relName/$item->ID");
$href = Director::absoluteURL($this->config()->api_base . "$relClass/$item->ID");
$innerParts[] = ArrayData::array_to_object(array(
"className" => $relClass,
"href" => "$href.json",
"id" => $item->ID
));
}
$serobj->$relName = $innerParts;
}
foreach($obj->manyMany() as $relName => $relClass) {
if(!singleton($relClass)->stat('api_access')) continue;
// Field filtering
if($fields && !in_array($relName, $fields)) continue;
if($this->customRelations && !in_array($relName, $this->customRelations)) continue;
$innerParts = array();
$items = $obj->$relName();
foreach($items as $item) {
//$href = Director::absoluteURL($this->config()->api_base . "$className/$id/$relName/$item->ID");
$href = Director::absoluteURL($this->config()->api_base . "$relClass/$item->ID");
$innerParts[] = ArrayData::array_to_object(array(
"className" => $relClass,
"href" => "$href.json",
"id" => $item->ID
));
}
$serobj->$relName = $innerParts;
}
}
return $serobj;
}
/**
* Generate a JSON representation of the given {@link SS_List}.
*
* @param SS_List $set
* @param array $fields
* @return String XML
*/
public function convertDataObjectSet(SS_List $set, $fields = null) {
$items = array();
foreach($set as $do) {
if(!$do->canView()) continue;
$items[] = $this->convertDataObjectToJSONObject($do, $fields);
}
$serobj = ArrayData::array_to_object(array(
"totalSize" => (is_numeric($this->totalSize)) ? $this->totalSize : null,
"items" => $items
));
return Convert::raw2json($serobj);
}
public function convertStringToArray($strData) {
return Convert::json2array($strData);
}
}