Problem/Motivation

Many sites are using the JSON:API Extras module to refine the API that JSON:API exposes by default. One such refinement is the ability to "alias" or disable resource type fields. To do that, JSON:API Extras is forced to depend on potentially unstable @internal PHP code. Also, custom module developers aren't able to write logic that could automatically alias resource type fields according to rules that suit their application (like automatically alias field_foo_bar to fooBar).

Proposed resolution

Add the following methods to \Drupal\jsonapi\ResourceType\ResourceTypeBuildEvent:

  • getFields() []ResourceTypeField
  • setPublicFieldName(ResourceTypeField $field, $public_field_name): void
  • disableField(ResourceTypeField $field): void

Remaining tasks

#3037039: Create a public API for indicating resource types should not be exposed

User interface changes

None.

API changes

There will be a new methods on an event.

Data model changes

None.

Release notes snippet

JSON:API resource type fields can now be aliased and disabled programmatically. See the change record (UPDATE THIS LINKED CR, IF POSSIBLE).

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

gabesullice created an issue. See original summary.

gabesullice’s picture

Title: Add a public API for aliasing JSON:API resource type fields » Add a public API for aliasing and disabling JSON:API resource type fields
Issue tags: +Contributed project soft blocker
gabesullice’s picture

Here's my initial implementation. It needs tests and will not apply without #3037039: Create a public API for indicating resource types should not be exposed

gabesullice’s picture

gabesullice’s picture

Issue summary: View changes
Issue tags: +Needs change record updates

If this lands with #3037039: Create a public API for indicating resource types should not be exposed then we should update that issue's change record rather than creating two CRs.

gabesullice’s picture

Title: Add a public API for aliasing and disabling JSON:API resource type fields » [PP-1] Add a public API for aliasing and disabling JSON:API resource type fields
Wim Leers’s picture

Looking great!

  1. +++ b/core/modules/jsonapi/src/ResourceType/ResourceTypeBuildEvent.php
    @@ -19,6 +20,13 @@ class ResourceTypeBuildEvent extends Event {
    +   * @var array|\Drupal\jsonapi\ResourceType\ResourceTypeField[]
    

    🤓🤔 I think we can remove array| here, the second part is sufficient?

  2. +++ b/core/modules/jsonapi/src/ResourceType/ResourceTypeBuildEvent.php
    @@ -31,9 +39,13 @@ class ResourceTypeBuildEvent extends Event {
    +    assert(Inspector::assertAllObjects($fields, ResourceTypeField::class));
    

    👍

  3. +++ b/core/modules/jsonapi/src/ResourceType/ResourceTypeBuildEvent.php
    @@ -76,4 +90,43 @@ public function resourceTypeShouldBeDisabled() {
    +  /**
    +   * Gets the current fields of the resource type to be built.
    +   */
    

    🤓 Missing @return.

  4. +++ b/core/modules/jsonapi/src/ResourceType/ResourceTypeBuildEvent.php
    @@ -76,4 +90,43 @@ public function resourceTypeShouldBeDisabled() {
    +   * Sets the public name of the given field on the resource type to be built.
    +   *
    +   * @param \Drupal\jsonapi\ResourceType\ResourceTypeField $field
    +   *   The field for which to set a public name.
    +   */
    +  public function disableField(ResourceTypeField $field) {
    

    🤓 Docblock is wrong. (This is not about public field name, but about disabling.)

  5. +++ b/core/modules/jsonapi/src/ResourceType/ResourceTypeRelationship.php
    @@ -60,4 +60,14 @@ public function withPublicName($public_name) {
    +  public function disabled() {
    +    $relationship = parent::disabled();
    +    return isset($this->relatableResourceTypes)
    +      ? $relationship->withRelatableResourceTypes($this->relatableResourceTypes)
    +      : $relationship;
    +  }
    

    🤩 Woah, elegant, fascinating.

  6. +++ b/core/modules/jsonapi/tests/modules/jsonapi_test_resource_type_building/src/EventSubscriber/ResourceTypeBuildEventSubscriber.php
    @@ -17,7 +17,13 @@ class ResourceTypeBuildEventSubscriber implements EventSubscriberInterface {
    +        ['disableResourceType'],
    +        ['aliasResourceTypeFields'],
    +        ['disableResourceTypeFields'],
    

    🤓 Übernit: I'm surprised these are arrays instead of strings.

gabesullice’s picture

  1. Gah, PHPStorm.
  2. :)
  3. Fixed.
  4. Fixed.
  5. :)
  6. This is the right way to do it, see the docs for getSubscribedEvents. The idea is that you can do ['methodName', $priority], but priority is optional, so it ends up ['string'].

Note: this was rerolled on top of #3037039-58: Create a public API for indicating resource types should not be exposed

Wim Leers’s picture

Status: Needs review » Postponed

I think this is RTBC :) But blocked on that other issue landing first, so Postponed it is for now.

Good job!

gabesullice’s picture

Title: [PP-1] Add a public API for aliasing and disabling JSON:API resource type fields » Add a public API for aliasing and disabling JSON:API resource type fields
Status: Postponed » Reviewed & tested by the community
Wim Leers’s picture

3085035-8.patch still applies cleanly, it just needed a re-test 😊

e0ipso’s picture

This looks great! Thanks for working on this. I can't wait to make use of this in JSON:API Extras.

jibran’s picture

Just a couple of questions.

  1. Do we need to update the old change record? https://www.drupal.org/node/3079797
    Just saw #5
  2. +++ b/core/modules/jsonapi/src/ResourceType/ResourceTypeBuildEvent.php
    @@ -48,12 +60,14 @@ protected function __construct($resource_type_name) {
    +  public static function createFromEntityTypeAndBundle(EntityTypeInterface $entity_type, $bundle, array $fields) {
    

    Do we need to default $fields to empty array?

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

effulgentsia’s picture

Adding reviewer credit

  • effulgentsia committed e686623 on 9.0.x
    Issue #3085035 by gabesullice, Wim Leers: Add a public API for aliasing...

  • effulgentsia committed 10f8062 on 8.9.x
    Issue #3085035 by gabesullice, Wim Leers: Add a public API for aliasing...

  • effulgentsia committed 4f3e3a6 on 8.8.x
    Issue #3085035 by gabesullice, Wim Leers: Add a public API for aliasing...
effulgentsia’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +8.8.0 release notes, +8.8.0 highlights

Do we need to default $fields to empty array?

I don't think so. As this is a new class that hasn't been in a tagged release of Drupal yet, we don't need to do it for BC reasons. And I don't think we want to support an API where people don't pass this in explicitly. But if I'm wrong on that, please file a followup.

Meanwhile, pushed this to 8.8.x and above.

Setting to NW for updating the CR from #3037039: Create a public API for indicating resource types should not be exposed.

Also, tagging for both release notes and highlights, because #3037039: Create a public API for indicating resource types should not be exposed has both those tags. It could potentially be the same release note and/or highlight entry for both issues, so long as it's worded to encompass both.

gabesullice’s picture

Status: Needs work » Fixed
Issue tags: -Needs change record updates

I updated the CR some time ago, but forget to update this issue's metadata. Thanks go to @xjm for a gentle reminder :)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.