View source
<?php
namespace Drupal\restful\Plugin\formatter;
use Drupal\restful\Exception\BadRequestException;
use Drupal\restful\Exception\InternalServerErrorException;
use Drupal\restful\Plugin\resource\Field\ResourceFieldCollectionInterface;
use Drupal\restful\Plugin\resource\Field\ResourceFieldInterface;
use Drupal\restful\Plugin\resource\Field\ResourceFieldResourceInterface;
class FormatterJson extends Formatter implements FormatterInterface {
protected $contentType = 'application/json; charset=utf-8';
public function prepare(array $data) {
if (!empty($data['status']) && floor($data['status'] / 100) != 2) {
$this->contentType = 'application/problem+json; charset=utf-8';
return $data;
}
$extracted = $this
->extractFieldValues($data);
$output = array(
'data' => $this
->limitFields($extracted),
);
if ($resource = $this
->getResource()) {
$request = $resource
->getRequest();
$data_provider = $resource
->getDataProvider();
if ($request
->isListRequest($resource
->getPath())) {
$output['count'] = $data_provider
->count();
if (variable_get('restful_show_access_denied', FALSE) && ($inaccessible_records = $data_provider
->getMetadata()
->get('inaccessible_records'))) {
$output['denied'] = empty($output['meta']['denied']) ? $inaccessible_records : $output['meta']['denied'] + $inaccessible_records;
}
}
if (method_exists($resource, 'additionalHateoas')) {
$output = array_merge($output, $resource
->additionalHateoas($output));
}
$this
->addHateoas($output);
}
return $output;
}
protected function extractFieldValues($data, array $parents = array(), array &$parent_hashes = array()) {
$output = array();
if ($this
->isCacheEnabled($data)) {
$parent_hashes[] = $this
->getCacheHash($data);
if ($cache = $this
->getCachedData($data)) {
return $cache->data;
}
}
foreach ($data as $public_field_name => $resource_field) {
if (!$resource_field instanceof ResourceFieldInterface) {
$parents[] = $public_field_name;
$output[$public_field_name] = static::isIterable($resource_field) ? $this
->extractFieldValues($resource_field, $parents, $parent_hashes) : $resource_field;
continue;
}
if (!$data instanceof ResourceFieldCollectionInterface) {
throw new InternalServerErrorException('Inconsistent output.');
}
$limit_fields = $data
->getLimitFields();
if (!$this
->isCacheEnabled($data) && $limit_fields && !in_array($resource_field
->getPublicName(), $limit_fields)) {
continue;
}
$value = $resource_field
->render($data
->getInterpreter());
if (static::isIterable($value) && $resource_field instanceof ResourceFieldResourceInterface) {
$value = $this
->extractFieldValues($value, $parents, $parent_hashes);
}
$output[$public_field_name] = $value;
}
if ($this
->isCacheEnabled($data)) {
$this
->setCachedData($data, $output, $parent_hashes);
}
return $output;
}
protected function addHateoas(array &$data) {
if (!($resource = $this
->getResource())) {
return;
}
$request = $resource
->getRequest();
$data['self'] = array(
'title' => 'Self',
'href' => $resource
->versionedUrl($resource
->getPath()),
);
$input = $request
->getParsedInput();
unset($input['page']);
unset($input['range']);
$input['page'] = $request
->getPagerInput();
$page = $input['page']['number'];
if ($page > 1) {
$query = $input;
$query['page']['number'] = $page - 1;
$data['previous'] = array(
'title' => 'Previous',
'href' => $resource
->versionedUrl('', array(
'query' => $query,
), TRUE),
);
}
$items_per_page = $this
->calculateItemsPerPage($resource);
$previous_items = ($page - 1) * $items_per_page;
if (isset($data['count']) && $data['count'] > count($data['data']) + $previous_items) {
$query = $input;
$query['page']['number'] = $page + 1;
$data['next'] = array(
'title' => 'Next',
'href' => $resource
->versionedUrl('', array(
'query' => $query,
), TRUE),
);
}
}
public function render(array $structured_data) {
return drupal_json_encode($structured_data);
}
public function getContentTypeHeader() {
return $this->contentType;
}
public function parseBody($body) {
if (!($decoded_json = drupal_json_decode($body))) {
throw new BadRequestException(sprintf('Invalid JSON provided: %s.', $body));
}
return $decoded_json;
}
}