View source
<?php
namespace Drupal\restful\Plugin\formatter;
use Drupal\Component\Plugin\PluginBase;
use Drupal\restful\Exception\ServerConfigurationException;
use Drupal\restful\Plugin\ConfigurablePluginTrait;
use Drupal\restful\Plugin\resource\Decorators\CacheDecoratedResourceInterface;
use Drupal\restful\Plugin\resource\Field\ResourceFieldBase;
use Drupal\restful\Plugin\resource\Field\ResourceFieldCollectionInterface;
use Drupal\restful\Plugin\resource\ResourceInterface;
use Drupal\restful\RenderCache\Entity\CacheFragment;
use Drupal\restful\RenderCache\RenderCache;
abstract class Formatter extends PluginBase implements FormatterInterface {
use ConfigurablePluginTrait;
protected $resource;
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
public function format(array $data) {
return $this
->render($this
->prepare($data));
}
public function getContentTypeHeader() {
return 'application/hal+json; charset=utf-8';
}
public function getResource() {
if (isset($this->resource)) {
return $this->resource;
}
$instance_configuration = $this
->getConfiguration();
if (empty($instance_configuration['resource'])) {
return NULL;
}
$this->resource = $instance_configuration['resource'] instanceof ResourceInterface ? $instance_configuration['resource'] : NULL;
return $this->resource;
}
public function setResource(ResourceInterface $resource) {
$this->resource = $resource;
$this
->setConfiguration(array(
'resource' => $resource,
));
}
public function parseBody($body) {
throw new ServerConfigurationException(sprintf('Invalid body parser for: %s.', $body));
}
protected static function isIterable($input) {
return is_array($input) || $input instanceof \Traversable || $input instanceof \stdClass;
}
protected function isCacheEnabled($data) {
if (!$data instanceof ResourceFieldCollectionInterface) {
return FALSE;
}
if (!($context = $data
->getContext())) {
return FALSE;
}
return !empty($context['cache_fragments']);
}
protected function getCachedData($data) {
if (!($render_cache = $this
->createCacheController($data))) {
return NULL;
}
return $render_cache
->get();
}
protected function getCacheHash($data) {
if (!($render_cache = $this
->createCacheController($data))) {
return NULL;
}
return $render_cache
->getCid();
}
protected function setCachedData($data, $output, array $parent_hashes = array()) {
if (!($render_cache = $this
->createCacheController($data))) {
return;
}
$render_cache
->set($output);
$fragments = $this
->cacheFragments($data);
foreach ($parent_hashes as $parent_hash) {
foreach ($fragments as $tag_type => $tag_value) {
$query = new \EntityFieldQuery();
$duplicate = (bool) $query
->entityCondition('entity_type', 'cache_fragment')
->propertyCondition('value', $tag_value)
->propertyCondition('type', $tag_type)
->propertyCondition('hash', $parent_hash)
->count()
->execute();
if ($duplicate) {
continue;
}
$cache_fragment = new CacheFragment(array(
'value' => $tag_value,
'type' => $tag_type,
'hash' => $parent_hash,
), 'cache_fragment');
try {
$cache_fragment
->save();
} catch (\Exception $e) {
watchdog_exception('restful', $e);
}
}
}
}
protected function createCacheController($data) {
if (!($cache_fragments = $this
->cacheFragments($data))) {
return NULL;
}
$cache_fragments
->set('formatter', $this
->getPluginId());
if (!($cached_resource = $this
->getResource())) {
return NULL;
}
if (!$cached_resource instanceof CacheDecoratedResourceInterface) {
return NULL;
}
return RenderCache::create($cache_fragments, $cached_resource
->getCacheController());
}
protected static function cacheFragments($data) {
$context = $data
->getContext();
if (!($cache_fragments = $context['cache_fragments'])) {
return NULL;
}
return $cache_fragments;
}
protected function limitFields($output, $allowed_fields = NULL) {
if (!isset($allowed_fields)) {
$request = ($resource = $this
->getResource()) ? $resource
->getRequest() : restful()
->getRequest();
$input = $request
->getParsedInput();
$allowed_fields = empty($input['fields']) ? FALSE : explode(',', $input['fields']);
}
if (!is_array($output)) {
return $output;
}
$result = array();
if (ResourceFieldBase::isArrayNumeric($output)) {
foreach ($output as $item) {
$result[] = $this
->limitFields($item, $allowed_fields);
}
return $result;
}
foreach ($output as $field_name => $field_contents) {
if ($allowed_fields !== FALSE && !in_array($field_name, $allowed_fields)) {
continue;
}
$result[$field_name] = $this
->limitFields($field_contents, $this
->unprefixInputOptions($allowed_fields, $field_name));
}
return $result;
}
protected static function unprefixInputOptions($allowed_fields, $prefix) {
if ($allowed_fields === FALSE) {
return FALSE;
}
$closure_unprefix = function ($field_limit) use ($prefix) {
if ($field_limit == $prefix) {
return NULL;
}
$pos = strpos($field_limit, $prefix . '.');
return $pos === 0 ? substr($field_limit, strlen($prefix . '.')) : NULL;
};
return array_filter(array_map($closure_unprefix, $allowed_fields));
}
protected function calculateItemsPerPage(ResourceInterface $resource) {
$data_provider = $resource
->getDataProvider();
$max_range = $data_provider
->getRange();
$original_input = $resource
->getRequest()
->getPagerInput();
$items_per_page = empty($original_input['size']) ? $max_range : $original_input['size'];
return $items_per_page > $max_range ? $max_range : $items_per_page;
}
}