View source
<?php
namespace Drupal\restful\Plugin\resource\DataProvider;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Doctrine\Common\Collections\ArrayCollection;
use Drupal\restful\Exception\ForbiddenException;
use Drupal\restful\Exception\InternalServerErrorException;
use Drupal\restful\Exception\ServerConfigurationException;
use Drupal\restful\Exception\InaccessibleRecordException;
use Drupal\restful\Http\Request;
use Drupal\restful\Http\RequestInterface;
use Drupal\restful\Plugin\resource\Decorators\CacheDecoratedResource;
use Drupal\restful\Plugin\resource\Field\ResourceFieldEntityAlterableInterface;
use Drupal\restful\Plugin\resource\Field\ResourceFieldResourceInterface;
use Drupal\restful\Plugin\resource\ResourceEntity;
use Drupal\restful\Plugin\resource\DataInterpreter\DataInterpreterEMW;
use Drupal\restful\Plugin\resource\DataInterpreter\DataInterpreterInterface;
use Drupal\restful\Plugin\resource\Field\ResourceFieldCollectionInterface;
use Drupal\restful\Plugin\resource\Field\ResourceFieldEntity;
use Drupal\restful\Exception\BadRequestException;
use Drupal\restful\Exception\UnprocessableEntityException;
use Drupal\restful\Plugin\resource\Field\ResourceFieldInterface;
use Drupal\restful\Plugin\resource\Resource;
use Drupal\restful\Plugin\resource\ResourceInterface;
use Drupal\restful\Util\ExplorableDecoratorInterface;
use Drupal\restful\Util\RelationalFilter;
use Drupal\restful\Util\RelationalFilterInterface;
use Drupal\entity_validator\ValidatorPluginManager;
class DataProviderEntity extends DataProvider implements DataProviderEntityInterface {
protected $entityType;
protected $bundles = array();
protected $EFQClass = '\\Drupal\\restful\\Util\\EntityFieldQuery';
public function __construct(RequestInterface $request, ResourceFieldCollectionInterface $field_definitions, $account, $plugin_id, $resource_path, array $options, $langcode = NULL) {
parent::__construct($request, $field_definitions, $account, $plugin_id, $resource_path, $options, $langcode);
if (empty($options['entityType'])) {
throw new InternalServerErrorException('The entity type was not provided.');
}
$this->entityType = $options['entityType'];
$options += array(
'bundles' => array(),
);
if ($options['bundles']) {
$this->bundles = $options['bundles'];
}
elseif ($options['bundles'] !== FALSE) {
$entity_info = entity_get_info($this->entityType);
$this->bundles = !empty($entity_info['bundles']) ? array_keys($entity_info['bundles']) : $entity_info['type'];
}
if (isset($options['EFQClass'])) {
$this->EFQClass = $options['EFQClass'];
}
$this
->setResourcePath($resource_path);
if (empty($this->options['urlParams'])) {
$this->options['urlParams'] = array(
'filter' => TRUE,
'sort' => TRUE,
'fields' => TRUE,
'loadByFieldName' => TRUE,
);
}
}
public function getCacheFragments($identifier) {
if (is_array($identifier)) {
$identifier = implode(ResourceInterface::IDS_SEPARATOR, $identifier);
}
$fragments = new ArrayCollection(array(
'resource' => CacheDecoratedResource::serializeKeyValue($this->pluginId, $this
->canonicalPath($identifier)),
'entity' => CacheDecoratedResource::serializeKeyValue($this->entityType, $this
->getEntityIdByFieldId($identifier)),
));
$options = $this
->getOptions();
switch ($options['renderCache']['granularity']) {
case DRUPAL_CACHE_PER_USER:
if ($uid = $this
->getAccount()->uid) {
$fragments
->set('user_id', (int) $uid);
}
break;
case DRUPAL_CACHE_PER_ROLE:
$fragments
->set('user_role', implode(',', $this
->getAccount()->roles));
break;
}
return $fragments;
}
protected function defaultSortInfo() {
return empty($this->options['sort']) ? array(
'id' => 'ASC',
) : $this->options['sort'];
}
public function getIndexIds() {
$result = $this
->getQueryForList()
->execute();
if (empty($result[$this->entityType])) {
return array();
}
$entity_ids = array_keys($result[$this->entityType]);
if (empty($this->options['idField'])) {
return $entity_ids;
}
$resource_field = $this->fieldDefinitions
->get($this->options['idField']);
$ids = array();
foreach ($entity_ids as $entity_id) {
$interpreter = new DataInterpreterEMW($this
->getAccount(), new \EntityDrupalWrapper($this->entityType, $entity_id));
$ids[] = $resource_field
->value($interpreter);
}
return $ids;
}
public function count() {
$query = $this
->getQueryCount();
return intval($query
->execute());
}
public function create($object) {
$this
->validateBody($object);
$entity_info = $this
->getEntityInfo();
$bundle_key = $entity_info['entity keys']['bundle'];
$bundle = reset($this->bundles);
$values = $bundle_key ? array(
$bundle_key => $bundle,
) : array();
$entity = entity_create($this->entityType, $values);
if ($this
->checkEntityAccess('create', $this->entityType, $entity) === FALSE) {
throw new ForbiddenException('You do not have access to create a new resource.');
}
$wrapper = entity_metadata_wrapper($this->entityType, $entity);
$this
->setPropertyValues($wrapper, $object, TRUE);
$old_request = $this
->getRequest();
$this
->getRequest()
->setMethod(RequestInterface::METHOD_GET);
$output = array(
$this
->view($wrapper
->getIdentifier()),
);
$this->request = $old_request;
return $output;
}
public function view($identifier) {
$entity_id = $this
->getEntityIdByFieldId($identifier);
if (!$this
->isValidEntity('view', $entity_id)) {
throw new InaccessibleRecordException(sprintf('The current user cannot access entity "%s".', $entity_id));
}
$field_collection = $this
->initResourceFieldCollection($identifier);
$input = $this
->getRequest()
->getParsedInput();
$limit_fields = !empty($input['fields']) ? explode(',', $input['fields']) : array();
$field_collection
->setLimitFields($limit_fields);
foreach ($this->fieldDefinitions as $resource_field) {
if (!$this
->methodAccess($resource_field) || !$resource_field
->access('view', $field_collection
->getInterpreter())) {
continue;
}
$field_collection
->set($resource_field
->id(), $resource_field);
}
return $field_collection;
}
public function viewMultiple(array $identifiers) {
$return = array();
foreach ($identifiers as $identifier) {
try {
$row = $this
->view($identifier);
} catch (InaccessibleRecordException $e) {
$row = NULL;
}
$return[] = $row;
}
return array_values(array_filter($return));
}
public function update($identifier, $object, $replace = FALSE) {
$this
->validateBody($object);
$entity_id = $this
->getEntityIdByFieldId($identifier);
$this
->isValidEntity('update', $entity_id);
$wrapper = entity_metadata_wrapper($this->entityType, $entity_id);
$this
->setPropertyValues($wrapper, $object, $replace);
$this
->setHttpHeader('Status', 201);
if (!empty($wrapper->url) && ($url = $wrapper->url
->value())) {
$this
->setHttpHeader('Location', $url);
}
$old_request = $this
->getRequest();
$this
->getRequest()
->setMethod(RequestInterface::METHOD_GET);
$output = array(
$this
->view($identifier),
);
$this->request = $old_request;
return $output;
}
public function remove($identifier) {
$this
->isValidEntity('delete', $identifier);
$wrapper = entity_metadata_wrapper($this->entityType, $identifier);
$wrapper
->delete();
$this
->setHttpHeader('Status', 204);
}
public function canonicalPath($path) {
$ids = explode(Resource::IDS_SEPARATOR, $path);
$canonical_ids = array_map(array(
$this,
'getEntityIdByFieldId',
), $ids);
return implode(Resource::IDS_SEPARATOR, $canonical_ids);
}
public function entityPreSave(\EntityDrupalWrapper $wrapper) {
}
public function entityValidate(\EntityDrupalWrapper $wrapper) {
if (!module_exists('entity_validator')) {
return;
}
try {
$validator_handler = ValidatorPluginManager::EntityValidator($wrapper
->type(), $wrapper
->getBundle());
} catch (PluginNotFoundException $e) {
return;
}
if ($validator_handler
->validate($wrapper
->value(), TRUE)) {
return;
}
$errors = $validator_handler
->getErrors(FALSE);
$map = array();
foreach ($this->fieldDefinitions as $resource_field_name => $resource_field) {
if (!($property = $resource_field
->getProperty())) {
continue;
}
$public_name = $resource_field
->getPublicName();
if (empty($errors[$public_name])) {
continue;
}
$map[$public_name] = $resource_field_name;
$params['@fields'][] = $resource_field_name;
}
if (empty($params['@fields'])) {
throw new BadRequestException('Invalid value(s) sent with the request.');
}
$params['@fields'] = implode(',', $params['@fields']);
$exception = new BadRequestException(format_plural(count($map), 'Invalid value in field @fields.', 'Invalid values in fields @fields.', $params));
foreach ($errors as $property_name => $messages) {
if (empty($map[$property_name])) {
continue;
}
$resource_field_name = $map[$property_name];
foreach ($messages as $message) {
$message['params']['@field'] = $resource_field_name;
$output = format_string($message['message'], $message['params']);
$exception
->addFieldError($resource_field_name, $output);
}
}
throw $exception;
}
protected function getEntityIdByFieldId($id) {
$request = $this
->getRequest();
$input = $request
->getParsedInput();
$public_property_name = empty($input['loadByFieldName']) ? NULL : $input['loadByFieldName'];
$public_property_name = $public_property_name ?: (empty($this->options['idField']) ? NULL : $this->options['idField']);
if (!$public_property_name) {
return $id;
}
if (!($public_field_info = $this->fieldDefinitions
->get($public_property_name)) || !$public_field_info
->getProperty()) {
throw new BadRequestException(format_string('Cannot load an entity using the field "@name"', array(
'@name' => $public_property_name,
)));
}
$query = $this
->getEntityFieldQuery();
$query
->range(0, 1);
$property = $public_field_info
->getProperty();
if (ResourceFieldEntity::propertyIsField($property)) {
$query
->fieldCondition($property, $public_field_info
->getColumn(), $id);
}
else {
$query
->propertyCondition($property, $id);
}
$result = $query
->execute();
if (empty($result[$this->entityType])) {
throw new UnprocessableEntityException(format_string('The entity ID @id by @name cannot be loaded.', array(
'@id' => $id,
'@name' => $public_property_name,
)));
}
$entity_id = key($result[$this->entityType]);
return $entity_id;
}
protected function getEntityFieldQuery() {
$query = $this
->EFQObject();
$entity_type = $this->entityType;
$query
->entityCondition('entity_type', $entity_type);
$entity_info = $this
->getEntityInfo();
if (!empty($this->bundles) && $entity_info['entity keys']['bundle']) {
$query
->entityCondition('bundle', $this->bundles, 'IN');
}
return $query;
}
public function EFQObject() {
$efq_class = $this->EFQClass;
return new $efq_class();
}
protected function getEntityInfo($type = NULL) {
return entity_get_info($type ? $type : $this->entityType);
}
protected function getQueryForList() {
$query = $this
->getEntityFieldQuery();
try {
$this
->queryForListSort($query);
} catch (ServerConfigurationException $e) {
watchdog_exception('restful', $e);
}
try {
$this
->queryForListFilter($query);
} catch (ServerConfigurationException $e) {
watchdog_exception('restful', $e);
}
$this
->queryForListPagination($query);
$this
->addExtraInfoToQuery($query);
return $query;
}
protected function getQueryCount() {
$query = $this
->getEntityFieldQuery();
try {
$this
->queryForListFilter($query);
} catch (BadRequestException $e) {
watchdog_exception('restful', $e);
}
$this
->addExtraInfoToQuery($query);
return $query
->count();
}
protected function addExtraInfoToQuery($query) {
parent::addExtraInfoToQuery($query);
if (empty($query->fieldConditions) && empty($query->order)) {
$query
->addTag($this->entityType . '_access');
}
$query
->addMetaData('restful_data_provider', $this);
}
protected function queryForListSort(\EntityFieldQuery $query) {
$resource_fields = $this->fieldDefinitions;
$sorts = $this
->parseRequestForListSort();
$sorts = $sorts ? $sorts : $this
->defaultSortInfo();
foreach ($sorts as $public_field_name => $direction) {
if (!($resource_field = $resource_fields
->get($public_field_name))) {
return;
}
$sort = array(
'public_field' => $public_field_name,
'direction' => $direction,
'resource_id' => $this->pluginId,
);
$sort = $this
->alterSortQuery($sort, $query);
if (!empty($sort['processed'])) {
continue;
}
if (!($property_name = $resource_field
->getProperty())) {
if (!$resource_field instanceof ResourceFieldEntityAlterableInterface) {
throw new BadRequestException('The current sort selection does not map to any entity property or Field API field.');
}
return;
}
if (ResourceFieldEntity::propertyIsField($property_name)) {
$query
->fieldOrderBy($property_name, $resource_field
->getColumn(), $sort['direction']);
}
else {
$column = $this
->getColumnFromProperty($property_name);
$query
->propertyOrderBy($column, $sort['direction']);
}
}
}
protected function queryForListFilter(\EntityFieldQuery $query) {
$resource_fields = $this->fieldDefinitions;
$filters = $this
->parseRequestForListFilter();
$this
->validateFilters($filters);
foreach ($filters as $filter) {
if (!($resource_field = $resource_fields
->get($filter['public_field']))) {
if (!static::isNestedField($filter['public_field'])) {
continue;
}
if (!empty($filter['target'])) {
continue;
}
$this
->addNestedFilter($filter, $query);
continue;
}
$filter = $this
->alterFilterQuery($filter, $query);
if (!empty($filter['processed'])) {
continue;
}
if (!($property_name = $resource_field
->getProperty())) {
if (!$resource_field instanceof ResourceFieldEntityAlterableInterface) {
throw new BadRequestException(sprintf('The current filter "%s" selection does not map to any entity property or Field API field and has no custom filtering.', $filter['public_field']));
}
return;
}
if (field_info_field($property_name)) {
if ($this::isMultipleValuOperator($filter['operator'][0])) {
$query
->fieldCondition($property_name, $resource_field
->getColumn(), $this
->getReferencedIds($filter['value'], $resource_field), $filter['operator'][0]);
continue;
}
for ($index = 0; $index < count($filter['value']); $index++) {
$query
->fieldCondition($property_name, $resource_field
->getColumn(), $this
->getReferencedId($filter['value'][$index], $resource_field), $filter['operator'][$index]);
}
}
else {
$column = $this
->getColumnFromProperty($property_name);
if ($this::isMultipleValuOperator($filter['operator'][0])) {
$query
->propertyCondition($column, $this
->getReferencedIds($filter['value'], $resource_field), $filter['operator'][0]);
continue;
}
for ($index = 0; $index < count($filter['value']); $index++) {
$query
->propertyCondition($column, $this
->getReferencedId($filter['value'][$index], $resource_field), $filter['operator'][$index]);
}
}
}
}
protected function alterFilterQuery(array $filter, \EntityFieldQuery $query) {
if (!($resource_field = $this->fieldDefinitions
->get($filter['public_field']))) {
return $filter;
}
if (!$resource_field instanceof ResourceFieldEntityAlterableInterface) {
if (!$resource_field instanceof ExplorableDecoratorInterface || !$resource_field
->isInstanceOf(ResourceFieldEntityAlterableInterface::class)) {
return $filter;
}
}
return $resource_field
->alterFilterEntityFieldQuery($filter, $query);
}
protected function alterSortQuery(array $sort, \EntityFieldQuery $query) {
if (!($resource_field = $this->fieldDefinitions
->get($sort['public_field']))) {
return $sort;
}
if (!$resource_field instanceof ResourceFieldEntityAlterableInterface) {
if (!$resource_field instanceof ExplorableDecoratorInterface || !$resource_field
->isInstanceOf(ResourceFieldEntityAlterableInterface::class)) {
return $sort;
}
}
return $resource_field
->alterSortEntityFieldQuery($sort, $query);
}
protected static function isMultipleValuOperator($operator_name) {
return in_array(strtoupper($operator_name), array(
'IN',
'NOT IN',
'BETWEEN',
));
}
protected function validateFilters(array $filters) {
foreach ($filters as $filter) {
if (empty($filter['target'])) {
continue;
}
$field_name_parts = explode('.', $filter['public_field']);
$target_parts = explode('.', $filter['target']);
foreach ($target_parts as $delta => $target_part) {
if ($target_part != $field_name_parts[$delta]) {
throw new BadRequestException(sprintf('The target "%s" should be a part of the field name "%s".', $filter['target'], $filter['public_field']));
}
}
}
}
protected function queryForListPagination(\EntityFieldQuery $query) {
list($offset, $range) = $this
->parseRequestForListPagination();
$query
->range($offset, $range);
}
protected static function isValidOperatorsForFilter(array $operators) {
$allowed_operators = array(
'=',
'>',
'<',
'>=',
'<=',
'<>',
'!=',
'BETWEEN',
'CONTAINS',
'IN',
'LIKE',
'NOT IN',
'STARTS_WITH',
);
foreach ($operators as $operator) {
if (!in_array($operator, $allowed_operators)) {
throw new BadRequestException(sprintf('Operator "%s" is not allowed for filtering on this resource. Allowed operators are: %s', $operator, implode(', ', $allowed_operators)));
}
}
}
protected static function isValidConjunctionForFilter($conjunction) {
$allowed_conjunctions = array(
'AND',
);
if (!in_array(strtoupper($conjunction), $allowed_conjunctions)) {
throw new BadRequestException(format_string('Conjunction "@conjunction" is not allowed for filtering on this resource. Allowed conjunctions are: !allowed', array(
'@conjunction' => $conjunction,
'!allowed' => implode(', ', $allowed_conjunctions),
)));
}
}
protected function getColumnFromProperty($property_name) {
$property_info = entity_get_property_info($this->entityType);
return $property_info['properties'][$property_name]['schema field'];
}
protected function isValidEntity($op, $entity_id) {
$entity_type = $this->entityType;
if (!ctype_digit((string) $entity_id) || !($entity = entity_load_single($entity_type, $entity_id))) {
throw new UnprocessableEntityException(sprintf('The entity ID %s does not exist.', $entity_id));
}
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
if (!empty($this->bundles) && !in_array($bundle, $this->bundles)) {
return FALSE;
}
if ($this
->checkEntityAccess($op, $entity_type, $entity) === FALSE) {
if ($op == 'view' && !$this
->getResourcePath()) {
$inaccessible_records = $this
->getMetadata()
->get('inaccessible_records');
$inaccessible_records[] = array(
'resource' => $this->pluginId,
'id' => $entity_id,
);
$this
->getMetadata()
->set('inaccessible_records', $inaccessible_records);
return FALSE;
}
throw new InaccessibleRecordException(sprintf('You do not have access to entity ID %s.', $entity_id));
}
return TRUE;
}
protected function checkEntityAccess($op, $entity_type, $entity) {
$account = $this
->getAccount();
return entity_access($op, $entity_type, $entity, $account);
}
protected function setPropertyValues(\EntityDrupalWrapper $wrapper, $object, $replace = FALSE) {
if (!is_array($object)) {
throw new BadRequestException('Bad input data provided. Please, check your input and your Content-Type header.');
}
$save = FALSE;
$original_object = $object;
$interpreter = new DataInterpreterEMW($this
->getAccount(), $wrapper);
$processed_fields = array();
$field_definitions = clone $this->fieldDefinitions;
foreach ($field_definitions as $public_field_name => $resource_field) {
if (!$this
->methodAccess($resource_field)) {
unset($original_object[$public_field_name]);
continue;
}
$property_name = $resource_field
->getProperty();
if ($resource_field
->isComputed()) {
unset($original_object[$public_field_name]);
continue;
}
$entity_property_access = $this::checkPropertyAccess($resource_field, 'edit', $interpreter);
if (!array_key_exists($public_field_name, $object)) {
if ($replace && $entity_property_access && !in_array($property_name, $processed_fields)) {
$field_value = NULL;
}
else {
continue;
}
}
else {
$field_value = $resource_field
->preprocess($object[$public_field_name]);
}
$resource_field
->set($field_value, $interpreter);
$entity_property_access = $this::checkPropertyAccess($resource_field, 'edit', $interpreter);
if (!$entity_property_access) {
throw new BadRequestException(format_string('Property @name cannot be set.', array(
'@name' => $public_field_name,
)));
}
$processed_fields[] = $property_name;
unset($original_object[$public_field_name]);
$save = TRUE;
}
if (!$save) {
throw new BadRequestException('No values were sent with the request');
}
if ($original_object) {
$error_message = format_plural(count($original_object), 'Property @names is invalid.', 'Properties @names are invalid.', array(
'@names' => implode(', ', array_keys($original_object)),
));
throw new BadRequestException($error_message);
}
$this
->entityPreSave($interpreter
->getWrapper());
$this
->entityValidate($interpreter
->getWrapper());
$wrapper
->save();
}
protected function validateBody($body) {
if (isset($body) && !is_array($body)) {
$message = sprintf('Incorrect object parsed: %s', print_r($body, TRUE));
throw new BadRequestException($message);
}
}
protected static function checkPropertyAccess(ResourceFieldInterface $resource_field, $op, DataInterpreterInterface $interpreter) {
return $resource_field
->access($op, $interpreter);
}
protected function getReferencedId($value, ResourceFieldInterface $resource_field) {
$field_definition = $resource_field
->getDefinition();
if (empty($field_definition['referencedIdProperty'])) {
return $value;
}
$field_info = field_info_field($resource_field
->getProperty());
$target_entity_type = NULL;
$bundles = array();
if (!$field_info) {
if ($resource_field
->getProperty() == 'uid') {
$target_entity_type = 'user';
}
elseif ($resource_field
->getProperty() == 'vid') {
$target_entity_type = 'taxonomy_vocabulary';
}
}
elseif (!empty($field_info['type']) && $field_info['type'] == 'entityreference') {
$target_entity_type = $field_info['settings']['target_type'];
$bundles = empty($field_info['settings']['handler_settings']['target_bundles']) ? array() : $field_info['settings']['handler_settings']['target_bundles'];
}
elseif (!empty($field_info['type']) && $field_info['type'] == 'file') {
$target_entity_type = 'file';
}
elseif (!empty($field_info['type']) && $field_info['type'] == 'taxonomy_term_reference') {
$target_entity_type = 'taxonomy_term';
foreach ($field_info['settings']['allowed_values'] as $allowed_value) {
$bundles[] = $allowed_value['vocabulary'];
}
}
if (empty($target_entity_type) && $resource_field instanceof ResourceFieldResourceInterface && ($resource_info = $resource_field
->getResource())) {
$instance_id = sprintf('%s:%d.%d', $resource_info['name'], $resource_info['majorVersion'], $resource_info['minorVersion']);
try {
$handler = restful()
->getResourceManager()
->getPlugin($instance_id);
if ($handler instanceof ResourceEntity) {
$target_entity_type = $handler
->getEntityType();
$bundles = $handler
->getBundles();
}
} catch (PluginNotFoundException $e) {
}
}
if (empty($target_entity_type)) {
return $value;
}
$query = $this
->EFQObject();
$query
->entityCondition('entity_type', $target_entity_type);
if (!empty($bundles)) {
$query
->entityCondition('bundle', $bundles, 'IN');
}
$id_property = $field_definition['referencedIdProperty'];
if (field_info_field($id_property)) {
$query
->fieldCondition($id_property, $resource_field
->getColumn(), $value);
}
else {
$query
->propertyCondition($id_property, $value);
}
$results = $query
->range(0, 1)
->execute();
if ($results[$target_entity_type]) {
return key($results[$target_entity_type]);
}
return $value;
}
protected function getReferencedIds(array $values, ResourceFieldInterface $resource_field) {
$output = array();
foreach ($values as $value) {
$output[] = $this
->getReferencedId($value, $resource_field);
}
return $output;
}
protected function addNestedFilter(array $filter, \EntityFieldQuery $query) {
$relational_filters = array();
foreach ($this
->getFieldsInfoFromPublicName($filter['public_field']) as $field_info) {
$relational_filters[] = new RelationalFilter($field_info['name'], $field_info['type'], $field_info['column'], $field_info['entity_type'], $field_info['bundles'], $field_info['target_column']);
}
$query
->addRelationship($filter + array(
'relational_filters' => $relational_filters,
));
}
protected function getFieldsInfoFromPublicName($name) {
$public_field_names = explode('.', $name);
$last_public_field_name = array_pop($public_field_names);
$fields = array();
$definitions = $this->fieldDefinitions;
foreach ($public_field_names as $index => $public_field_name) {
$resource_field = $definitions
->get($public_field_name);
if (!$resource_field || !($resource = $resource_field
->getResource())) {
throw new ServerConfigurationException(sprintf('The nested field %s cannot be accessed because %s has no resource associated to it.', $name, $public_field_name));
}
list($item, $definitions) = $this
->getFieldsFromPublicNameItem($resource_field);
$fields[] = $item;
}
if (!($resource_field = $definitions
->get($last_public_field_name))) {
throw new BadRequestException(sprintf('Invalid nested field provided %s', $last_public_field_name));
}
$property = $resource_field
->getProperty();
$item = array(
'name' => $property,
'type' => ResourceFieldEntity::propertyIsField($property) ? RelationalFilterInterface::TYPE_FIELD : RelationalFilterInterface::TYPE_PROPERTY,
'entity_type' => NULL,
'bundles' => array(),
'target_column' => NULL,
);
$item['column'] = $item['type'] == RelationalFilterInterface::TYPE_FIELD ? $resource_field
->getColumn() : NULL;
$fields[] = $item;
return $fields;
}
protected function getFieldsFromPublicNameItem(ResourceFieldResourceInterface $resource_field) {
$property = $resource_field
->getProperty();
$item = array(
'name' => $property,
'type' => ResourceFieldEntity::propertyIsField($property) ? RelationalFilterInterface::TYPE_FIELD : RelationalFilterInterface::TYPE_PROPERTY,
'entity_type' => NULL,
'bundles' => array(),
'target_column' => $resource_field
->getTargetColumn(),
);
$item['column'] = $item['type'] == RelationalFilterInterface::TYPE_FIELD ? $resource_field
->getColumn() : NULL;
$resource = $resource_field
->getResourcePlugin();
$definitions = $resource
->getFieldDefinitions();
$item['entity_type'] = $resource
->getEntityType();
$item['bundles'] = $resource
->getBundles();
return array(
$item,
$definitions,
);
}
protected function initDataInterpreter($identifier) {
$id = $identifier;
$entity_id = $this
->getEntityIdByFieldId($id);
$wrapper = entity_metadata_wrapper($this->entityType, $entity_id);
$wrapper
->language($this
->getLangCode());
return new DataInterpreterEMW($this
->getAccount(), $wrapper);
}
}