You are here

protected function FormatterJsonApi::renormalize in RESTful 7.2

Move the embedded resources to the included key.

Change the data structure from an auto-contained hierarchical tree to the final JSON API structure. The auto-contained tree has redundant information because every branch contains all the information that is embedded in there and can be used as stand alone.

Parameters

array $output: The output array to modify to include the compounded documents.

array $included: Pool of documents to compound.

bool|string[] $allowed_fields: The sparse fieldset information. FALSE to select all fields.

array $includes_parents: An array containing the included path until the current field being processed.

Return value

array The processed data.

1 call to FormatterJsonApi::renormalize()
FormatterJsonApi::prepare in src/Plugin/formatter/FormatterJsonApi.php
Massages the raw data to create a structured array to pass to the renderer.

File

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

Class

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

Namespace

Drupal\restful\Plugin\formatter

Code

protected function renormalize(array $output, array &$included, $allowed_fields = NULL, $includes_parents = array()) {
  static $depth = -1;
  $depth++;
  if (!isset($allowed_fields)) {
    $request = ($resource = $this
      ->getResource()) ? $resource
      ->getRequest() : restful()
      ->getRequest();
    $input = $request
      ->getParsedInput();

    // Set the field limits to false if there are no limits.
    $allowed_fields = empty($input['fields']) ? FALSE : explode(',', $input['fields']);
  }
  if (!is_array($output)) {

    // $output is a simple value.
    $depth--;
    return $output;
  }
  $result = array();
  if (ResourceFieldBase::isArrayNumeric($output)) {
    foreach ($output as $item) {
      $result[] = $this
        ->renormalize($item, $included, $allowed_fields, $includes_parents);
    }
    $depth--;
    return $result;
  }
  if (!empty($output['#resource_name'])) {
    $result['type'] = $output['#resource_name'];
  }
  if (!empty($output['#resource_id'])) {
    $result['id'] = $output['#resource_id'];
  }
  if (!isset($output['#fields'])) {
    $depth--;
    return $this
      ->renormalize($output, $included, $allowed_fields, $includes_parents);
  }
  foreach ($output['#fields'] as $field_name => $field_contents) {
    if ($allowed_fields !== FALSE && !in_array($field_name, $allowed_fields)) {
      continue;
    }
    if (empty($field_contents['#embedded'])) {
      $result['attributes'][$field_name] = $field_contents;
    }
    else {

      // Handle single and multiple relationships.
      $rel = array();
      $single_item = $field_contents['#cardinality'] == 1;
      $relationship_links = empty($field_contents['#relationship_links']) ? NULL : $field_contents['#relationship_links'];
      unset($field_contents['#embedded']);
      unset($field_contents['#cardinality']);
      unset($field_contents['#relationship_links']);
      foreach ($field_contents as $field_item) {
        $include_links = empty($field_item['#include_links']) ? NULL : $field_item['#include_links'];
        unset($field_contents['#include_links']);
        $field_path = $this
          ->buildIncludePath($includes_parents, $field_name);
        $field_item = $this
          ->populateCachePlaceholder($field_item, $field_path);
        unset($field_item['#cache_placeholder']);
        $element = $field_item['#relationship_info'];
        unset($field_item['#relationship_info']);
        $include_key = $field_item['#resource_plugin'] . '--' . $field_item['#resource_id'];
        $nested_allowed_fields = $this
          ->unprefixInputOptions($allowed_fields, $field_name);

        // If the list of the child allowed fields is empty, but the parent is
        // part of the includes, it means that the consumer meant to include
        // all the fields in the children.
        if (is_array($allowed_fields) && empty($nested_allowed_fields) && in_array($field_name, $allowed_fields)) {
          $nested_allowed_fields = FALSE;
        }

        // If we get here is because the relationship is included in the
        // sparse fieldset. That means that in this context, empty field
        // limits mean all the fields.
        $new_includes_parents = $includes_parents;
        $new_includes_parents[] = $field_name;
        $included[$field_path][$include_key] = $this
          ->renormalize($field_item, $included, $nested_allowed_fields, $new_includes_parents);
        $included[$field_path][$include_key] += $include_links ? array(
          'links' => $include_links,
        ) : array();
        $rel[$include_key] = $element;
      }

      // Only place the relationship info.
      $result['relationships'][$field_name] = array(
        'data' => $single_item ? reset($rel) : array_values($rel),
      );
      if (!empty($relationship_links)) {
        $result['relationships'][$field_name]['links'] = $relationship_links;
      }
    }
  }

  // Set the links for every item.
  if (!empty($output['#links'])) {
    $result['links'] = $output['#links'];
  }

  // Decrease the depth level.
  $depth--;
  return $result;
}