Commit 4f3e3a61 authored by effulgentsia's avatar effulgentsia

Issue #3085035 by gabesullice, Wim Leers: Add a public API for aliasing and...

Issue #3085035 by gabesullice, Wim Leers: Add a public API for aliasing and disabling JSON:API resource type fields

(cherry picked from commit e6866239)
parent 30e8f31b
......@@ -2,6 +2,7 @@
namespace Drupal\jsonapi\ResourceType;
use Drupal\Component\Assertion\Inspector;
use Drupal\Core\Entity\EntityTypeInterface;
use Symfony\Component\EventDispatcher\Event;
......@@ -20,6 +21,13 @@ class ResourceTypeBuildEvent extends Event {
*/
protected $resourceTypeName;
/**
* The fields of the resource type to be built.
*
* @var \Drupal\jsonapi\ResourceType\ResourceTypeField[]
*/
protected $fields;
/**
* Whether the JSON:API resource type to be built should be disabled.
*
......@@ -35,9 +43,13 @@ class ResourceTypeBuildEvent extends Event {
*
* @param string $resource_type_name
* A JSON:API resource type name.
* @param \Drupal\jsonapi\ResourceType\ResourceTypeField[] $fields
* The fields of the resource type to be built.
*/
protected function __construct($resource_type_name) {
protected function __construct($resource_type_name, array $fields) {
assert(Inspector::assertAllObjects($fields, ResourceTypeField::class));
$this->resourceTypeName = $resource_type_name;
$this->fields = $fields;
}
/**
......@@ -48,12 +60,14 @@ protected function __construct($resource_type_name) {
* @param string $bundle
* A bundle name for the resource type to be built. If the entity type does
* not have bundles, the entity type ID.
* @param \Drupal\jsonapi\ResourceType\ResourceTypeField[] $fields
* The fields of the resource type to be built.
*
* @return \Drupal\jsonapi\ResourceType\ResourceTypeBuildEvent
* A new event.
*/
public static function createFromEntityTypeAndBundle(EntityTypeInterface $entity_type, $bundle) {
return new static(sprintf('%s--%s', $entity_type->id(), $bundle));
public static function createFromEntityTypeAndBundle(EntityTypeInterface $entity_type, $bundle, array $fields) {
return new static(sprintf('%s--%s', $entity_type->id(), $bundle), $fields);
}
/**
......@@ -83,4 +97,46 @@ public function resourceTypeShouldBeDisabled() {
return $this->disabled;
}
/**
* Gets the current fields of the resource type to be built.
*
* @return \Drupal\jsonapi\ResourceType\ResourceTypeField[]
* The current fields of the resource type to be built.
*/
public function getFields() {
return $this->fields;
}
/**
* 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.
* @param string $public_field_name
* The public field name to set.
*/
public function setPublicFieldName(ResourceTypeField $field, $public_field_name) {
foreach ($this->fields as $index => $value) {
if ($field === $value) {
$this->fields[$index] = $value->withPublicName($public_field_name);
return;
}
}
}
/**
* Disables 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) {
foreach ($this->fields as $index => $value) {
if ($field === $value) {
$this->fields[$index] = $value->disabled();
return;
}
}
}
}
......@@ -95,6 +95,16 @@ public function withPublicName($public_name) {
return new static($this->internalName, $public_name, $this->enabled, $this->hasOne);
}
/**
* Gets a new instance of the field that is disabled.
*
* @return static
* A new instance of the field that is disabled.
*/
public function disabled() {
return new static($this->internalName, $this->publicName, FALSE, $this->hasOne);
}
/**
* Whether the field is enabled.
*
......
......@@ -60,4 +60,14 @@ public function withPublicName($public_name) {
: $relationship;
}
/**
* {@inheritdoc}
*/
public function disabled() {
$relationship = parent::disabled();
return isset($this->relatableResourceTypes)
? $relationship->withRelatableResourceTypes($this->relatableResourceTypes)
: $relationship;
}
}
......@@ -151,10 +151,12 @@ public function all() {
protected function createResourceType(EntityTypeInterface $entity_type, $bundle) {
$raw_fields = $this->getAllFieldNames($entity_type, $bundle);
$internalize_resource_type = $entity_type->isInternal();
$fields = static::getFields($raw_fields, $entity_type, $bundle);
if (!$internalize_resource_type) {
$event = ResourceTypeBuildEvent::createFromEntityTypeAndBundle($entity_type, $bundle);
$event = ResourceTypeBuildEvent::createFromEntityTypeAndBundle($entity_type, $bundle, $fields);
$this->eventDispatcher->dispatch(ResourceTypeBuildEvents::BUILD, $event);
$internalize_resource_type = $event->resourceTypeShouldBeDisabled();
$fields = $event->getFields();
}
return new ResourceType(
$entity_type->id(),
......@@ -164,7 +166,7 @@ protected function createResourceType(EntityTypeInterface $entity_type, $bundle)
static::isLocatableResourceType($entity_type, $bundle),
static::isMutableResourceType($entity_type, $bundle),
static::isVersionableResourceType($entity_type),
static::getFields($raw_fields, $entity_type, $bundle)
$fields
);
}
......
......@@ -17,7 +17,13 @@ class ResourceTypeBuildEventSubscriber implements EventSubscriberInterface {
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [ResourceTypeBuildEvents::BUILD => 'disableResourceType'];
return [
ResourceTypeBuildEvents::BUILD => [
['disableResourceType'],
['aliasResourceTypeFields'],
['disableResourceTypeFields'],
],
];
}
/**
......@@ -33,4 +39,40 @@ public function disableResourceType(ResourceTypeBuildEvent $event) {
}
}
/**
* Aliases any resource type fields that have been aliased by a test.
*
* @param \Drupal\jsonapi\ResourceType\ResourceTypeBuildEvent $event
* The build event.
*/
public function aliasResourceTypeFields(ResourceTypeBuildEvent $event) {
$aliases = \Drupal::state()->get('jsonapi_test_resource_type_builder.resource_type_field_aliases', []);
$resource_type_name = $event->getResourceTypeName();
if (in_array($resource_type_name, array_keys($aliases), TRUE)) {
foreach ($event->getFields() as $field) {
if (isset($aliases[$resource_type_name][$field->getInternalName()])) {
$event->setPublicFieldName($field, $aliases[$resource_type_name][$field->getInternalName()]);
}
}
}
}
/**
* Disables any resource type fields that have been aliased by a test.
*
* @param \Drupal\jsonapi\ResourceType\ResourceTypeBuildEvent $event
* The build event.
*/
public function disableResourceTypeFields(ResourceTypeBuildEvent $event) {
$aliases = \Drupal::state()->get('jsonapi_test_resource_type_builder.disabled_resource_type_fields', []);
$resource_type_name = $event->getResourceTypeName();
if (in_array($resource_type_name, array_keys($aliases), TRUE)) {
foreach ($event->getFields() as $field) {
if (isset($aliases[$resource_type_name][$field->getInternalName()]) && $aliases[$resource_type_name][$field->getInternalName()] === TRUE) {
$event->disableField($field);
}
}
}
}
}
......@@ -167,4 +167,44 @@ public function testResourceTypeDisabling() {
$this->assertTrue($this->resourceTypeRepository->getByTypeName('user--user')->isInternal());
}
/**
* Tests that resource type fields can be aliased per resource type.
*/
public function testResourceTypeFieldAliasing() {
$this->assertSame($this->resourceTypeRepository->getByTypeName('node--article')->getPublicName('uid'), 'uid');
$this->assertSame($this->resourceTypeRepository->getByTypeName('node--page')->getPublicName('uid'), 'uid');
$resource_type_field_aliases = [
'node--article' => [
'uid' => 'author',
],
'node--page' => [
'uid' => 'owner',
],
];
\Drupal::state()->set('jsonapi_test_resource_type_builder.resource_type_field_aliases', $resource_type_field_aliases);
Cache::invalidateTags(['jsonapi_resource_types']);
$this->assertSame($this->resourceTypeRepository->getByTypeName('node--article')->getPublicName('uid'), 'author');
$this->assertSame($this->resourceTypeRepository->getByTypeName('node--page')->getPublicName('uid'), 'owner');
}
/**
* Tests that resource type fields can be disabled per resource type.
*/
public function testResourceTypeFieldDisabling() {
$this->assertTrue($this->resourceTypeRepository->getByTypeName('node--article')->isFieldEnabled('uid'));
$this->assertTrue($this->resourceTypeRepository->getByTypeName('node--page')->isFieldEnabled('uid'));
$disabled_resource_type_fields = [
'node--article' => [
'uid' => TRUE,
],
'node--page' => [
'uid' => FALSE,
],
];
\Drupal::state()->set('jsonapi_test_resource_type_builder.disabled_resource_type_fields', $disabled_resource_type_fields);
Cache::invalidateTags(['jsonapi_resource_types']);
$this->assertFalse($this->resourceTypeRepository->getByTypeName('node--article')->isFieldEnabled('uid'));
$this->assertTrue($this->resourceTypeRepository->getByTypeName('node--page')->isFieldEnabled('uid'));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment