You are here

protected function FormatterJsonApi::embedField in RESTful 7.2

Embeds the final contents of a field.

If the field is a relationship to another resource, it embeds the resource.

Parameters

ResourceFieldInterface $resource_field: The resource field being processed. If it is a related resource, this is used to extract the contents of the resource. If not, it's used to extract the simple value.

string $parent_id: ID in the parent resource where this is being embedded.

DataInterpreterInterface $interpreter: The context for the $resource_field.

array $parents: Tracks the parents of the field to construct the dot notation for the field name.

string[] $parent_hashes: An array that holds the name of the parent cache hashes that lead to the current data structure.

Return value

array The contents for the JSON API attribute or relationship.

1 call to FormatterJsonApi::embedField()
FormatterJsonApi::extractFieldValues in src/Plugin/formatter/FormatterJsonApi.php
Extracts the actual values from the resource fields.

File

src/Plugin/formatter/FormatterJsonApi.php, line 424
Contains \Drupal\restful\Plugin\formatter\FormatterJsonApi.

Class

FormatterJsonApi
Class FormatterJsonApi @package Drupal\restful\Plugin\formatter

Namespace

Drupal\restful\Plugin\formatter

Code

protected function embedField(ResourceFieldInterface $resource_field, $parent_id, DataInterpreterInterface $interpreter, array &$parents, array &$parent_hashes) {
  static $embedded_resources = array();

  // If the field points to a resource that can be included, include it
  // right away.
  if (!$resource_field instanceof ResourceFieldResourceInterface) {
    return $resource_field
      ->render($interpreter);
  }

  // Check if the resource needs to be included. If not then set 'full_view'
  // to false.
  $cardinality = $resource_field
    ->getCardinality();
  $output = array();
  $public_field_name = $resource_field
    ->getPublicName();
  if (!($ids = $resource_field
    ->compoundDocumentId($interpreter))) {
    return NULL;
  }
  $ids = $cardinality == 1 ? $ids = array(
    $ids,
  ) : $ids;
  $resource_info = $resource_field
    ->getResource();
  $empty_value = array(
    '#fields' => array(),
    '#embedded' => TRUE,
    '#resource_plugin' => sprintf('%s:%d.%d', $resource_info['name'], $resource_info['majorVersion'], $resource_info['minorVersion']),
    '#cache_placeholder' => array(
      'parents' => array_merge($parents, array(
        $public_field_name,
      )),
      'parent_hashes' => $parent_hashes,
    ),
  );
  $value = array_map(function ($id) use ($empty_value) {
    return $empty_value + array(
      '#resource_id' => $id,
    );
  }, $ids);
  if ($this
    ->needsIncluding($resource_field, $parents)) {
    $cid = sprintf('%s:%d.%d--%s', $resource_info['name'], $resource_info['majorVersion'], $resource_info['minorVersion'], implode(',', $ids));
    if (!isset($embedded_resources[$cid])) {
      $result = $resource_field
        ->render($interpreter);
      if (empty($result) || !static::isIterable($result)) {
        $embedded_resources[$cid] = $result;
        return $result;
      }
      $new_parents = $parents;
      $new_parents[] = $public_field_name;
      $result = $this
        ->extractFieldValues($result, $new_parents, $parent_hashes);
      $embedded_resources[$cid] = $cardinality == 1 ? array(
        $result,
      ) : $result;
    }
    $value = $embedded_resources[$cid];
  }

  // At this point we are dealing with an embed.
  $value = array_filter($value);

  // Set the resource for the reference.
  $resource_plugin = $resource_field
    ->getResourcePlugin();
  foreach ($value as $value_item) {
    $id = $value_item['#resource_id'];
    $basic_info = array(
      'type' => $resource_field
        ->getResourceMachineName(),
      'id' => (string) $id,
    );

    // We want to be able to include only the images in articles.images,
    // but not articles.related.images. That's why we need the path
    // including the parents.
    $item = array(
      '#resource_name' => $basic_info['type'],
      '#resource_plugin' => $resource_plugin
        ->getPluginId(),
      '#resource_id' => $basic_info['id'],
      '#include_links' => array(
        'self' => $resource_plugin
          ->versionedUrl($basic_info['id']),
      ),
      '#relationship_info' => array(
        'type' => $basic_info['type'],
        'id' => $basic_info['id'],
      ),
    ) + $value_item;
    $output[] = $item;
  }

  // If there is a resource plugin for the parent, set the related
  // links.
  $links = array();
  if ($resource = $this
    ->getResource()) {
    $links['related'] = $resource
      ->versionedUrl('', array(
      'absolute' => TRUE,
      'query' => array(
        'filter' => array(
          $public_field_name => reset($ids),
        ),
      ),
    ));
    $links['self'] = $resource_plugin
      ->versionedUrl($parent_id . '/relationships/' . $public_field_name);
  }
  return $output + array(
    '#embedded' => TRUE,
    '#cardinality' => $cardinality,
    '#relationship_links' => $links,
  );
}