You are here

public function ContentEntityTypeResolver::resolveRecursive in GraphQL 8

Same name and namespace in other branches
  1. 8.2 src/TypeResolver/ContentEntityTypeResolver.php \Drupal\graphql\TypeResolver\ContentEntityTypeResolver::resolveRecursive()

Parameters

mixed $type:

Return value

\Fubhy\GraphQL\Type\Definition\Types\TypeInterface|null

Overrides TypedDataTypeResolver::resolveRecursive

File

src/TypeResolver/ContentEntityTypeResolver.php, line 82

Class

ContentEntityTypeResolver
Resolves the schema for content entities.

Namespace

Drupal\graphql\TypeResolver

Code

public function resolveRecursive($type) {

  /** @var \Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface $type */
  $entityTypeId = $type
    ->getEntityTypeId();
  $bundleInfo = $this->entityManager
    ->getBundleInfo($entityTypeId);
  $bundleKeys = array_keys($bundleInfo);

  // The bundles available for this entity type.
  $availableBundles = array_diff($bundleKeys, [
    $entityTypeId,
  ]);

  // The bundles defined as constraint on the the type definition.
  $constraintBundles = $type
    ->getBundles();
  $constraintBundles = $constraintBundles ? array_diff($bundleKeys, $constraintBundles) : [];
  $constraintBundles = array_intersect($constraintBundles, $availableBundles);

  // We currently do not support multiple bundle constraints although we could
  // potentially support that in the future through union types.
  $constraintBundle = count($constraintBundles) === 1 ? reset($constraintBundles) : NULL;

  // Check if we've already built the type definitions for this entity type.
  $cacheKey = isset($constraintBundle) ? $constraintBundle : $entityTypeId;
  if (array_key_exists($entityTypeId, $this->cachedTypes)) {
    return $this->cachedTypes[$entityTypeId][$cacheKey];
  }

  // Resolve complex data definitions lazily due to recursive definitions.
  return function () use ($entityTypeId, $cacheKey) {
    if (array_key_exists($entityTypeId, $this->cachedTypes)) {
      return $this->cachedTypes[$entityTypeId][$cacheKey];
    }

    // Initialize the static cache for this entity type.
    $staticCache =& $this->cachedTypes[$entityTypeId];
    $staticCache = [];

    // Retrieve the field map for the entity type (contains base and bundle
    // specific fields).
    $fieldMap = $this
      ->getEntityTypeFieldMap($entityTypeId);
    $baseFields = $fieldMap['base'];
    $entityTypeName = StringHelper::formatTypeName("entity:{$entityTypeId}");
    if (!empty($fieldMap['bundles'])) {

      // If there are bundles, create an interface type definition and the
      // object type definition for all available bundles.
      $objectTypeResolver = [
        __CLASS__,
        'getObjectTypeFromData',
      ];
      $staticCache[$entityTypeId] = new InterfaceType($entityTypeName, $baseFields, $objectTypeResolver);
      $typeInterfaces = [
        $staticCache[$entityTypeId],
      ];
      foreach ($fieldMap['bundles'] as $bundleKey => $bundleFields) {
        $bundleName = StringHelper::formatTypeName("entity:{$entityTypeId}:{$bundleKey}");
        $staticCache[$bundleKey] = new ObjectType($bundleName, $bundleFields + $baseFields, $typeInterfaces);
      }
    }
    else {

      // If there are no bundles, simply handle the entity type as a
      // stand-alone object type.
      $staticCache[$entityTypeId] = !empty($baseFields) ? new ObjectType($entityTypeName, $baseFields) : new NullType();
    }
    return $staticCache[$cacheKey];
  };
}