You are here

class ResourceFieldEntityReference in RESTful 7.2

Class ResourceFieldEntityReference.

@package Drupal\restful\Plugin\resource\Field

Hierarchy

Expanded class hierarchy of ResourceFieldEntityReference

File

src/Plugin/resource/Field/ResourceFieldEntityReference.php, line 23
Contains \Drupal\restful\Plugin\resource\Field\ResourceFieldEntityReference.

Namespace

Drupal\restful\Plugin\resource\Field
View source
class ResourceFieldEntityReference extends ResourceFieldEntity implements ResourceFieldEntityReferenceInterface {

  /**
   * Property where the ID should be retrieved from.
   *
   * If empty, the entity ID will be used. It's either the property or Field API
   * field name.
   *
   * @var string
   */
  protected $referencedIdProperty;

  /**
   * Constructs a ResourceFieldEntityReference.
   *
   * @param array $field
   *   Contains the field values.
   *
   * @param RequestInterface $request
   *   The request.
   */
  public function __construct(array $field, RequestInterface $request) {
    parent::__construct($field, $request);
    if (!empty($field['referencedIdProperty'])) {
      $this->referencedIdProperty = $field['referencedIdProperty'];
    }

    // TODO: Document referencedIdProperty.
  }

  /**
   * {@inheritdoc}
   */
  public function preprocess($value) {
    if (!$value) {

      // If value is empty, return NULL, so no new entity will be created.
      return NULL;
    }
    $cardinality = $this
      ->getCardinality();
    if ($cardinality != 1 && !is_array($value)) {

      // If the field is entity reference type and its cardinality larger than
      // 1 set value to an array.
      $value = explode(',', $value);
    }
    if ($cardinality != 1 && ResourceFieldBase::isArrayNumeric($value)) {

      // Set the cardinality to 1 to process each value as a single value item.
      $this
        ->setCardinality(1);

      // For multiple value items, pre-process them separately.
      $values = array();
      foreach ($value as $item) {
        $values[] = $this
          ->preprocess($item);
      }
      $this
        ->setCardinality($cardinality);
      return $values;
    }

    // If the provided value is the ID to the referenced entity, then do not do
    // a sub-request.
    if (!is_array($value) || empty($value['body'])) {

      // Allow to pass an array with the ID instead of the ID directly.
      return !empty($value['id']) && array_keys($value) == array(
        'id',
      ) ? $value['id'] : $value;
    }

    /* @var ResourceFieldCollectionInterface $merged_value */
    $merged_value = $this
      ->mergeEntityFromReference($value);
    return $merged_value
      ->getInterpreter()
      ->getWrapper()
      ->getIdentifier();
  }

  /**
   * Helper function; Create an entity from a a sub-resource.
   *
   * @param mixed $value
   *   The single value for the sub-request.
   *
   * @return mixed
   *   The value to set using the wrapped property.
   */
  protected function mergeEntityFromReference($value) {
    $resource = $this
      ->getResource();
    if (empty($resource) || empty($value['body'])) {

      // Field is not defined as "resource", which means it only accepts an
      // integer as a valid value.
      // Or, we are passing an integer and cardinality is 1. That means that we
      // are passing the ID of the referenced entity. Hence setting the new
      // value to the reference field.
      return $value;
    }

    // Get the resource data provider and make the appropriate operations.
    // We need to create a RequestInterface object for the sub-request.
    $resource_data_provider = DataProviderResource::init(static::subRequest($value), $resource['name'], array(
      $resource['majorVersion'],
      $resource['minorVersion'],
    ));

    // We are always dealing with the single value.
    $merged = $resource_data_provider
      ->merge(static::subRequestId($value), $value['body']);
    return reset($merged);
  }

  /**
   * {@inheritdoc}
   */
  public static function subRequest(array $value) {
    if (empty($value['request'])) {
      throw new BadRequestException('Malformed body payload. Missing "request" key for the sub-request.');
    }
    if (empty($value['request']['method'])) {
      throw new BadRequestException('Malformed body payload. Missing "method" int the "request" key for the sub-request.');
    }
    $request_user_info = $value['request'] + array(
      'path' => NULL,
      'query' => array(),
      'csrf_token' => NULL,
    );
    $headers = empty($request_user_info['headers']) ? array() : $request_user_info['headers'];
    $request_user_info['headers'] = new HttpHeaderBag($headers);
    $request_user_info['via_router'] = FALSE;
    $request_user_info['cookies'] = $_COOKIE;
    $request_user_info['files'] = $_FILES;
    $request_user_info['server'] = $_SERVER;
    return Request::create($request_user_info['path'], $request_user_info['query'], $request_user_info['method'], $request_user_info['headers'], $request_user_info['via_router'], $request_user_info['csrf_token'], $request_user_info['cookies'], $request_user_info['files'], $request_user_info['server']);
  }

  /**
   * Get the ID of the resource this write sub-request is for.
   *
   * @param array $value
   *   The value provided for this sub-request item.
   *
   * @return string
   *   The ID.
   */
  protected static function subRequestId($value) {
    if ($value['request']['method'] == RequestInterface::METHOD_POST) {

      // If the request is for post, then disregard any possible ID.
      return NULL;
    }
    return empty($value['id']) ? NULL : $value['id'];
  }

  /**
   * {@inheritdoc}
   */
  public function value(DataInterpreterInterface $interpreter) {
    $value = $this->decorated
      ->value($interpreter);
    if (isset($value)) {

      // Let the decorated resolve callbacks.
      return $value;
    }

    // Check user has access to the property.
    if (!$this
      ->access('view', $interpreter)) {
      return NULL;
    }
    $resource = $this
      ->getResource();

    // If the field definition does not contain a resource, or it is set
    // explicitly to fullView FALSE, then return only the entity ID.
    if ($resource || !empty($resource) && $resource['fullView'] !== FALSE || $this
      ->getFormatter()) {

      // Let the resource embedding to the parent class.
      return parent::value($interpreter);
    }

    // Since this is a reference field (a field that points to other entities,
    // we can know for sure that the property wrappers are instances of
    // \EntityDrupalWrapper or lists of them.
    $property_wrapper = $this
      ->propertyWrapper($interpreter);
    if (!$property_wrapper
      ->value()) {

      // If there is no referenced entity, return.
      return NULL;
    }

    // If this is a multivalue field, then call recursively on the items.
    if ($property_wrapper instanceof \EntityListWrapper) {
      $values = array();
      foreach ($property_wrapper
        ->getIterator() as $item_wrapper) {
        $values[] = $this
          ->referencedId($item_wrapper);
      }
      return $values;
    }

    /* @var $property_wrapper \EntityDrupalWrapper */
    return $this
      ->referencedId($property_wrapper);
  }

  /**
   * Helper function to get the referenced entity ID.
   *
   * @param \EntityDrupalWrapper $property_wrapper
   *   The wrapper for the referenced entity.
   *
   * @return mixed
   *   The ID.
   */
  protected function referencedId($property_wrapper) {
    $identifier = $property_wrapper
      ->getIdentifier();
    if (!$this->referencedIdProperty) {
      return $identifier;
    }
    try {
      return $identifier ? $property_wrapper->{$this->referencedIdProperty}
        ->value() : NULL;
    } catch (\EntityMetadataWrapperException $e) {

      // An exception will be raised for broken entity reference fields.
      return NULL;
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getRequest() {
    return $this->decorated
      ->getRequest();
  }

  /**
   * {@inheritdoc}
   */
  public function setRequest(RequestInterface $request) {
    $this->decorated
      ->setRequest($request);
  }

  /**
   * {@inheritdoc}
   */
  public function getDefinition() {
    return $this->decorated
      ->getDefinition();
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ResourceFieldEntity::$bundle protected property The bundle name.
ResourceFieldEntity::$column protected property If the property is a field, set the column that would be used in queries. For example, the default column for a text field would be "value". Defaults to the first column returned by field_info_field(), otherwise FALSE.
ResourceFieldEntity::$decorated protected property Decorated resource field.
ResourceFieldEntity::$entityType protected property The entity type.
ResourceFieldEntity::$formatter protected property Used for rendering the value of a configurable field using Drupal field API's formatter. The value is the $display value that is passed to field_view_field().
ResourceFieldEntity::$imageStyles protected property Array of image styles to apply to this resource field maps to an image field.
ResourceFieldEntity::$property protected property A copy of the underlying property.
ResourceFieldEntity::$subProperty protected property A sub property name of a property to take from it the content.
ResourceFieldEntity::$wrapperMethod protected property The wrapper's method name to perform on the field. This can be used for example to get the entity label, by setting the value to "label". Defaults to "value".
ResourceFieldEntity::$wrapperMethodOnEntity protected property A Boolean to indicate on what to perform the wrapper method. If TRUE the method will perform on the entity (e.g. $wrapper->label()) and FALSE on the property or sub property (e.g. $wrapper->field_reference->label()).
ResourceFieldEntity::access public function Overrides ResourceFieldInterface::access
ResourceFieldEntity::addDefaults public function Almost all the defaults come are applied by the object's property defaults. Overrides ResourceFieldInterface::addDefaults
ResourceFieldEntity::addMetadata public function Add metadata to the field. Overrides ResourceFieldInterface::addMetadata
ResourceFieldEntity::autoDiscovery public function
ResourceFieldEntity::buildResourceMetadataItem protected function Builds a metadata item for a field value. 1
ResourceFieldEntity::compoundDocumentId public function Fetches the embedded identifier(s) for the current resource field, if any. Overrides ResourceFieldInterface::compoundDocumentId
ResourceFieldEntity::create public static function Factory. Overrides ResourceFieldInterface::create
ResourceFieldEntity::decorate public function Decorate the object. Overrides ResourceFieldEntityInterface::decorate
ResourceFieldEntity::entityTypeWrapper protected function Gets the \EntityStructureWrapper for the entity type.
ResourceFieldEntity::executeProcessCallbacks public function Executes the process callbacks. Overrides ResourceFieldInterface::executeProcessCallbacks 2
ResourceFieldEntity::fieldClassName public static function Get the class name to use based on the field definition.
ResourceFieldEntity::fieldInfoField protected static function Gets statically cached information about a field.
ResourceFieldEntity::fieldValue protected function Get value from a property.
ResourceFieldEntity::formatterValue protected function Get value from a field rendered by Drupal field API's formatter.
ResourceFieldEntity::getAccessCallbacks public function Overrides ResourceFieldInterface::getAccessCallbacks
ResourceFieldEntity::getBundle public function Overrides ResourceFieldEntityInterface::getBundle
ResourceFieldEntity::getCallback public function Overrides ResourceFieldInterface::getCallback
ResourceFieldEntity::getCardinality public function Gets the cardinality of the wrapped field. Overrides ResourceFieldInterface::getCardinality
ResourceFieldEntity::getColumn public function Overrides ResourceFieldEntityInterface::getColumn
ResourceFieldEntity::getEntityType public function Overrides ResourceFieldEntityInterface::getEntityType
ResourceFieldEntity::getFormatter public function Overrides ResourceFieldEntityInterface::getFormatter
ResourceFieldEntity::getImageStyles public function Overrides ResourceFieldEntityInterface::getImageStyles
ResourceFieldEntity::getImageUris public static function Get the image URLs based on the configured image styles. Overrides ResourceFieldEntityInterface::getImageUris
ResourceFieldEntity::getMetadata public function Add metadata to the field. Overrides ResourceFieldInterface::getMetadata
ResourceFieldEntity::getMethods public function Overrides ResourceFieldInterface::getMethods
ResourceFieldEntity::getProcessCallbacks public function Overrides ResourceFieldInterface::getProcessCallbacks
ResourceFieldEntity::getProperty public function Overrides ResourceFieldInterface::getProperty
ResourceFieldEntity::getPublicFieldInfo public function Gets the public field info object. Overrides ResourceFieldInterface::getPublicFieldInfo
ResourceFieldEntity::getPublicName public function Overrides ResourceFieldInterface::getPublicName
ResourceFieldEntity::getResource public function Overrides ResourceFieldInterface::getResource
ResourceFieldEntity::getSubProperty public function Overrides ResourceFieldEntityInterface::getSubProperty
ResourceFieldEntity::getWrapperMethod public function Overrides ResourceFieldEntityInterface::getWrapperMethod
ResourceFieldEntity::id public function Gets the ID of the resource field. Overrides ResourceFieldInterface::id
ResourceFieldEntity::isArrayNumeric public static function Helper method to determine if an array is numeric. Overrides ResourceFieldInterface::isArrayNumeric
ResourceFieldEntity::isComputed public function Checks if the current field is computed. Overrides ResourceFieldInterface::isComputed
ResourceFieldEntity::isWrapperMethodOnEntity public function Overrides ResourceFieldEntityInterface::isWrapperMethodOnEntity
ResourceFieldEntity::nestedDottedChildren protected function Get the children of a query string parameter that apply to the field.
ResourceFieldEntity::nestedDottedFilters protected function Process the filter query string for the relevant sub-query.
ResourceFieldEntity::populatePublicInfoField protected function Populate public info field with Property API information.
ResourceFieldEntity::propertyIdentifier protected function Helper function to get the identifier from a property wrapper. 1
ResourceFieldEntity::propertyIsField public static function Checks if a given string represents a Field API field. Overrides ResourceFieldEntityInterface::propertyIsField
ResourceFieldEntity::propertyOnEntity protected function Sets the resource field property to the schema field in the entity.
ResourceFieldEntity::propertyWrapper protected function Get the wrapper for the property associated to the current field.
ResourceFieldEntity::render public function Gets the value of a field and applies all process callbacks to it. Overrides ResourceFieldInterface::render
ResourceFieldEntity::resourceValue protected function Get value for a field based on another resource.
ResourceFieldEntity::set public function Gets the value for the field given a data source. Overrides ResourceFieldInterface::set
ResourceFieldEntity::setAccessCallbacks public function Overrides ResourceFieldInterface::setAccessCallbacks
ResourceFieldEntity::setBundle public function Overrides ResourceFieldEntityInterface::setBundle
ResourceFieldEntity::setCallback public function Overrides ResourceFieldInterface::setCallback
ResourceFieldEntity::setCardinality public function Set the cardinality. Overrides ResourceFieldInterface::setCardinality
ResourceFieldEntity::setColumn public function Overrides ResourceFieldEntityInterface::setColumn
ResourceFieldEntity::setEntityType public function Overrides ResourceFieldEntityInterface::setEntityType
ResourceFieldEntity::setFormatter public function Overrides ResourceFieldEntityInterface::setFormatter
ResourceFieldEntity::setImageStyles public function Overrides ResourceFieldEntityInterface::setImageStyles
ResourceFieldEntity::setMethods public function Overrides ResourceFieldInterface::setMethods
ResourceFieldEntity::setProcessCallbacks public function Overrides ResourceFieldInterface::setProcessCallbacks
ResourceFieldEntity::setProperty public function Overrides ResourceFieldInterface::setProperty
ResourceFieldEntity::setPublicFieldInfo public function Gets the public field info object. Overrides ResourceFieldInterface::setPublicFieldInfo
ResourceFieldEntity::setPublicName public function Overrides ResourceFieldInterface::setPublicName
ResourceFieldEntity::setResource public function Overrides ResourceFieldInterface::setResource
ResourceFieldEntity::setSubProperty public function Overrides ResourceFieldEntityInterface::setSubProperty
ResourceFieldEntity::setWrapperMethod public function Overrides ResourceFieldEntityInterface::setWrapperMethod
ResourceFieldEntity::setWrapperMethodOnEntity public function Overrides ResourceFieldEntityInterface::setWrapperMethodOnEntity
ResourceFieldEntity::singleValue protected function Returns the value for the current single field.
ResourceFieldEntityReference::$referencedIdProperty protected property Property where the ID should be retrieved from.
ResourceFieldEntityReference::getDefinition public function Gets the original field definition as declared in Resource::publicFields(). Overrides ResourceFieldEntity::getDefinition
ResourceFieldEntityReference::getRequest public function Get the request in the data provider. Overrides ResourceFieldEntity::getRequest 1
ResourceFieldEntityReference::mergeEntityFromReference protected function Helper function; Create an entity from a a sub-resource.
ResourceFieldEntityReference::preprocess public function Massage the value to set according to the format expected by the wrapper. Overrides ResourceFieldEntity::preprocess
ResourceFieldEntityReference::referencedId protected function Helper function to get the referenced entity ID. Overrides ResourceFieldEntity::referencedId 1
ResourceFieldEntityReference::setRequest public function Set the request. Overrides ResourceFieldEntity::setRequest 1
ResourceFieldEntityReference::subRequest public static function Creates a request object for the sub-request. Overrides ResourceFieldEntityReferenceInterface::subRequest
ResourceFieldEntityReference::subRequestId protected static function Get the ID of the resource this write sub-request is for.
ResourceFieldEntityReference::value public function Gets the value for the field given a data source. Overrides ResourceFieldEntity::value
ResourceFieldEntityReference::__construct public function Constructs a ResourceFieldEntityReference. Overrides ResourceFieldEntity::__construct