wotapi-8.x-1.x-dev/src/Normalizer/ResourceObjectNormalizer.php

src/Normalizer/ResourceObjectNormalizer.php
<?php

namespace Drupal\wotapi\Normalizer;

use Drupal\Component\Annotation\AnnotationInterface;
use Drupal\Component\Assertion\Inspector;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\wotapi\Routing\Routes;
use Drupal\wotapi\WotApiResource\ResourceObject;
use Drupal\wotapi\Normalizer\Value\CacheableNormalization;
use Drupal\wotapi\Normalizer\Value\CacheableOmission;

/**
 * Converts the WOT:API module ResourceObject into a WOT:API array structure.
 *
 * @internal WOT:API maintains no PHP API since its API is the HTTP API. This
 *   class may change at any time and this will break any dependencies on it.
 */
class ResourceObjectNormalizer extends NormalizerBase {

  const DEPTH_KEY = __CLASS__ . '_depth';

  /**
   * {@inheritdoc}
   */
  protected $supportedInterfaceOrClass = ResourceObject::class;

  /**
   * {@inheritdoc}
   */
  public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool {
    return parent::supportsDenormalization($data, $type, $format, $context = []);
    // return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function normalize($object, $format = NULL, array $context = []) {
    assert($object instanceof ResourceObject);
    // If the fields to use were specified, only output those field values.
    $context['resource_object'] = $object;
    $resource_type = $object->getResourceType();
    $resource_type_name = $resource_type->getTypeName();
    $fields = $object->getFields();
    // Get the bundle ID of the requested resource. This is used to determine if
    // this is a bundle level resource or an entity level resource.
    if (!empty($context['sparse_fieldset'][$resource_type_name])) {
      $field_names = $context['sparse_fieldset'][$resource_type_name];
    }
    else {
      $field_names = array_keys($fields);
    }

    // The property returns a single value: {"temperature": 21}
    // See https://iot.mozilla.org/wot/#property-resource
    if ($resource_type->getEntityTypeId() == 'wotapi_property') {
      $properties = [];
      foreach ($fields as $field_name => $field) {
        if ($field->getFieldDefinition() instanceof FieldConfig) {
          $source_field = $object->getSourceField();
          if ($source_field) {
            $properties[$source_field->getName()] = $this->serializeField($field, $context, $format);
          }
        }
      }
      if (count($properties) == 1) {
        return CacheableNormalization::aggregate($properties)->withCacheableDependency($object);
      }
    }

    $normalizer_values = [];
    $normalizer_actions = [];
    foreach ($fields as $field_name => $field) {
      $in_sparse_fieldset = in_array($field_name, $field_names);
      // Omit fields not listed in sparse fieldsets.
      if (!$in_sparse_fieldset) {
        continue;
      }

      if ($this->isActionField($field_name, $field)) {
        foreach ($field->getValue() as $key => $value) {
          $action_id = array_values($value)[0];
          $action = \Drupal::service('wotapi_action.handler')->getAction($action_id);
          $normalizer_actions += $this->normalizeAction($action, $format, $context);
        }
        unset($fields, $field_name);
      }
      else {
        $normalizer_values[$field_name] = $this->serializeField($field, $context, $format);
      }
    }

    $id = \Drupal::request()->getSchemeAndHttpHost() . Url::fromRoute(Routes::getRouteName($resource_type, 'individual'), ['entity' => $object->getId()])->toString();
    $normalization = [
      "@context" => CacheableNormalization::permanent("https://iot.mozilla.org/schemas/"),
      'id' => CacheableNormalization::permanent($id),
    ];

    $related_resource_types = $resource_type->getRelatableResourceTypes();
    $relationship_field_names = array_keys($related_resource_types);
    $attributes = array_diff_key($normalizer_values, array_flip($relationship_field_names));
    $normalization += $attributes;

    $properties_names = [];
    foreach ($related_resource_types as $property_field_name => $related) {
      foreach ($related as $K => $related_resource) {
        $related_resource_name = $related_resource->getEntityTypeId();
        if ($related_resource_name == 'wotapi_property') {
          array_push($properties_names, $property_field_name);
        }
      }
    }
    $properties_key = array_intersect_key($normalizer_values, array_flip($properties_names));
    if (count($properties_key) > 0) {
      $normalization['properties'] = CacheableNormalization::aggregate($properties_key);
    }

    if (!is_null($normalizer_actions)) {
      $normalization['actions'] = CacheableNormalization::permanent($normalizer_actions);
    }

    $links = [];
    foreach (['properties', 'actions', 'events'] as $link_rel) {
      $links[] = ['rel' => $link_rel, 'href' => $id . '/' . $link_rel];
    }
    $normalization['links'] = CacheableNormalization::permanent($links);

    $obj = CacheableNormalization::aggregate($normalization)->withCacheableDependency($object);
    return $obj;
  }

  /**
   *
   */
  public function isActionField($field_name, $field) {
    if (is_object($field)
        && $field->getFieldDefinition()->getType() == 'wotapi_action') {
      return TRUE;
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function normalizeAction($object, $format = NULL, array $context = []) {
    $attributes = [];
    foreach ($object as $key => $value) {
      switch ($key) {
        case 'id':
        case 'call':
        case 'access':
          break;

        default:
          $child = $value instanceof AnnotationInterface ? $value->get() : $value;
          if (isset($context[static::DEPTH_KEY]) && $child instanceof AnnotationInterface || (is_array($child)) && Inspector::assertAllObjects($child, AnnotationInterface::class)) {
            if ($context[static::DEPTH_KEY] === 0) {
              break;
            }
            $context[static::DEPTH_KEY] -= 1;
          }
          $attributes[$key] = $this->serializer->normalize($child, $format, $context);
      }
    }
    // $normalized = [
    //      'type' => static::getAnnotationType($object),
    //      'id' => $object->getId(),
    //    ];
    $normalized = [];
    $at_type = $object->getAtType();
    if (!is_null($at_type)) {
      $normalized['@type'] = $at_type;
    }

    $normalized += $attributes;
    unset($normalized['at_type']);

    $action_input = call_user_func([$object->getClass(), 'input']);
    if (!is_null($action_input)) {
      $normalized['input'] = $action_input;
    }

    $action[$object->getId()] = $normalized;

    return $action;
  }

  /**
   * Serializes a given field.
   *
   * @param mixed $field
   *   The field to serialize.
   * @param array $context
   *   The normalization context.
   * @param string $format
   *   The serialization format.
   *
   * @return \Drupal\wotapi\Normalizer\Value\CacheableNormalization
   *   The normalized value.
   */
  protected function serializeField($field, array $context, $format) {
    // Only content entities contain FieldItemListInterface fields. Since config
    // entities do not have "real" fields and therefore do not have field access
    // restrictions.
    if ($field instanceof FieldItemListInterface) {
      $field_access_result = $field->access('view', $context['account'], TRUE);
      if (!$field_access_result->isAllowed()) {
        return new CacheableOmission(CacheableMetadata::createFromObject($field_access_result));
      }
      $normalized_field = $this->serializer->normalize($field, $format, $context);
      assert($normalized_field instanceof CacheableNormalization);
      return $normalized_field->withCacheableDependency(CacheableMetadata::createFromObject($field_access_result));
    }
    else {
      // @todo Replace this workaround after https://www.drupal.org/node/3043245
      //   or remove the need for this in https://www.drupal.org/node/2942975.
      //   See \Drupal\layout_builder\Normalizer\LayoutEntityDisplayNormalizer.
      if ($context['resource_object']->getResourceType()->getDeserializationTargetClass() === 'Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay' && $context['resource_object']->getField('third_party_settings') === $field) {
        unset($field['layout_builder']['sections']);
      }

      // Config "fields" in this case are arrays or primitives and do not need
      // to be normalized.
      return CacheableNormalization::permanent($field);
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc