function ResourceTypeRepository::getFields

Same name in other branches
  1. 8.9.x core/modules/jsonapi/src/ResourceType/ResourceTypeRepository.php \Drupal\jsonapi\ResourceType\ResourceTypeRepository::getFields()
  2. 10 core/modules/jsonapi/src/ResourceType/ResourceTypeRepository.php \Drupal\jsonapi\ResourceType\ResourceTypeRepository::getFields()
  3. 11.x core/modules/jsonapi/src/ResourceType/ResourceTypeRepository.php \Drupal\jsonapi\ResourceType\ResourceTypeRepository::getFields()

Gets the field mapping for the given field names and entity type + bundle.

Parameters

string[] $field_names: All field names on a bundle of the given entity type.

\Drupal\Core\Entity\EntityTypeInterface $entity_type: The entity type for which to get the field mapping.

string $bundle: The bundle to assess.

Return value

\Drupal\jsonapi\ResourceType\ResourceTypeField[] An array of JSON:API resource type fields keyed by internal field names.

2 calls to ResourceTypeRepository::getFields()
AliasingResourceTypeRepository::getFields in core/modules/jsonapi/tests/modules/jsonapi_test_field_aliasing/src/ResourceType/AliasingResourceTypeRepository.php
Gets the field mapping for the given field names and entity type + bundle.
ResourceTypeRepository::createResourceType in core/modules/jsonapi/src/ResourceType/ResourceTypeRepository.php
Creates a ResourceType value object for the given entity type + bundle.
1 method overrides ResourceTypeRepository::getFields()
AliasingResourceTypeRepository::getFields in core/modules/jsonapi/tests/modules/jsonapi_test_field_aliasing/src/ResourceType/AliasingResourceTypeRepository.php
Gets the field mapping for the given field names and entity type + bundle.

File

core/modules/jsonapi/src/ResourceType/ResourceTypeRepository.php, line 223

Class

ResourceTypeRepository
Provides a repository of all JSON:API resource types.

Namespace

Drupal\jsonapi\ResourceType

Code

protected function getFields(array $field_names, EntityTypeInterface $entity_type, $bundle) {
    assert(Inspector::assertAllStrings($field_names));
    assert($entity_type instanceof ContentEntityTypeInterface || $entity_type instanceof ConfigEntityTypeInterface);
    assert(is_string($bundle) && !empty($bundle), 'A bundle ID is required. Bundleless entity types should pass the entity type ID again.');
    // JSON:API resource identifier objects are sufficient to identify
    // entities. By exposing all fields as attributes, we expose unwanted,
    // confusing or duplicate information:
    // - exposing an entity's ID (which is not a UUID) is bad, but it's
    //   necessary for certain Drupal-coupled clients, so we alias it by
    //   prefixing it with `drupal_internal__`.
    // - exposing an entity's UUID as an attribute is useless (it's already part
    //   of the mandatory "id" attribute in JSON:API), so we disable it in most
    //   cases.
    // - exposing its revision ID as an attribute will compete with any profile
    //   defined meta members used for resource object versioning.
    // @see http://jsonapi.org/format/#document-resource-identifier-objects
    $id_field_name = $entity_type->getKey('id');
    $uuid_field_name = $entity_type->getKey('uuid');
    if ($uuid_field_name && $uuid_field_name !== 'id') {
        $fields[$uuid_field_name] = new ResourceTypeAttribute($uuid_field_name, NULL, FALSE);
    }
    $fields[$id_field_name] = new ResourceTypeAttribute($id_field_name, "drupal_internal__{$id_field_name}");
    if ($entity_type->isRevisionable() && ($revision_id_field_name = $entity_type->getKey('revision'))) {
        $fields[$revision_id_field_name] = new ResourceTypeAttribute($revision_id_field_name, "drupal_internal__{$revision_id_field_name}");
    }
    if ($entity_type instanceof ConfigEntityTypeInterface) {
        // The '_core' key is reserved by Drupal core to handle complex edge cases
        // correctly. Data in the '_core' key is irrelevant to clients reading
        // configuration, and is not allowed to be set by clients writing
        // configuration: it is for Drupal core only, and managed by Drupal core.
        // @see https://www.drupal.org/node/2653358
        $fields['_core'] = new ResourceTypeAttribute('_core', NULL, FALSE);
    }
    $is_fieldable = $entity_type->entityClassImplements(FieldableEntityInterface::class);
    if ($is_fieldable) {
        $field_definitions = $this->entityFieldManager
            ->getFieldDefinitions($entity_type->id(), $bundle);
    }
    // For all other fields,  use their internal field name also as their public
    // field name.  Unless they're called "id" or "type": those names are
    // reserved by the JSON:API spec.
    // @see http://jsonapi.org/format/#document-resource-object-fields
    $reserved_field_names = [
        'id',
        'type',
    ];
    foreach (array_diff($field_names, array_keys($fields)) as $field_name) {
        $alias = $field_name;
        // Alias the fields reserved by the JSON:API spec with `{entity_type}_`.
        if (in_array($field_name, $reserved_field_names, TRUE)) {
            $alias = $entity_type->id() . '_' . $field_name;
        }
        // The default, which applies to most fields: expose as-is.
        $field_definition = $is_fieldable && !empty($field_definitions[$field_name]) ? $field_definitions[$field_name] : NULL;
        $is_relationship_field = $field_definition && static::isReferenceFieldDefinition($field_definition);
        $has_one = !$field_definition || $field_definition->getFieldStorageDefinition()
            ->getCardinality() === 1;
        $fields[$field_name] = $is_relationship_field ? new ResourceTypeRelationship($field_name, $alias, TRUE, $has_one) : new ResourceTypeAttribute($field_name, $alias, TRUE, $has_one);
    }
    // With all fields now aliased, detect any conflicts caused by the
    // automatically generated aliases above.
    foreach (array_intersect($reserved_field_names, array_keys($fields)) as $reserved_field_name) {
        
        /** @var \Drupal\jsonapi\ResourceType\ResourceTypeField $aliased_reserved_field */
        $aliased_reserved_field = $fields[$reserved_field_name];
        
        /** @var \Drupal\jsonapi\ResourceType\ResourceTypeField $field */
        foreach (array_diff_key($fields, array_flip([
            $reserved_field_name,
        ])) as $field) {
            if ($aliased_reserved_field->getPublicName() === $field->getPublicName()) {
                throw new \LogicException("The generated alias '{$aliased_reserved_field->getPublicName()}' for field name '{$aliased_reserved_field->getInternalName()}' conflicts with an existing field. Please report this in the JSON:API issue queue!");
            }
        }
    }
    // Special handling for user entities that allows a JSON:API user agent to
    // access the display name of a user. This is useful when displaying the
    // name of a node's author.
    // @see \Drupal\jsonapi\JsonApiResource\ResourceObject::extractContentEntityFields()
    // @todo: eliminate this special casing in https://www.drupal.org/project/drupal/issues/3079254.
    if ($entity_type->id() === 'user') {
        $fields['display_name'] = new ResourceTypeAttribute('display_name');
    }
    return $fields;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.