class Relationship
Same name in other branches
- 9 core/modules/jsonapi/src/JsonApiResource/Relationship.php \Drupal\jsonapi\JsonApiResource\Relationship
- 8.9.x core/modules/jsonapi/src/JsonApiResource/Relationship.php \Drupal\jsonapi\JsonApiResource\Relationship
- 10 core/modules/jsonapi/src/JsonApiResource/Relationship.php \Drupal\jsonapi\JsonApiResource\Relationship
Represents references from one resource object to other resource object(s).
@internal JSON: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.
Hierarchy
- class \Drupal\jsonapi\JsonApiResource\Relationship implements \Drupal\jsonapi\JsonApiResource\TopLevelDataInterface
Expanded class hierarchy of Relationship
See also
https://www.drupal.org/project/drupal/issues/3032787
4 files declare their use of Relationship
- EntityResource.php in core/
modules/ jsonapi/ src/ Controller/ EntityResource.php - RelationshipNormalizer.php in core/
modules/ jsonapi/ src/ Normalizer/ RelationshipNormalizer.php - RelationshipNormalizerTest.php in core/
modules/ jsonapi/ tests/ src/ Kernel/ Normalizer/ RelationshipNormalizerTest.php - ResourceObjectNormalizer.php in core/
modules/ jsonapi/ src/ Normalizer/ ResourceObjectNormalizer.php
28 string references to 'Relationship'
- ConfigHandler::buildForm in core/
modules/ views_ui/ src/ Form/ Ajax/ ConfigHandler.php - ConfigHandler::buildForm in core/
modules/ views_ui/ src/ Form/ Ajax/ ConfigHandler.php - DisplayPluginBase::getFieldLabels in core/
modules/ views/ src/ Plugin/ views/ display/ DisplayPluginBase.php - DisplayPluginBase::validate in core/
modules/ views/ src/ Plugin/ views/ display/ DisplayPluginBase.php - DisplayTest::testMissingRelationship in core/
modules/ views/ tests/ src/ Functional/ Plugin/ DisplayTest.php - Tests display validation when a required relationship is missing.
File
-
core/
modules/ jsonapi/ src/ JsonApiResource/ Relationship.php, line 22
Namespace
Drupal\jsonapi\JsonApiResourceView source
class Relationship implements TopLevelDataInterface {
/**
* The context resource object of the relationship.
*
* A relationship object represents references from a resource object in
* which it’s defined to other resource objects. Respectively, the "context"
* of the relationship and the "target(s)" of the relationship.
*
* A relationship object's context either comes from the resource object that
* contains it or, in the case that the relationship object is accessed
* directly via a relationship URL, from its `self` URL, which should identify
* the resource to which it belongs.
*
* @var \Drupal\jsonapi\JsonApiResource\ResourceObject
*
* @see https://jsonapi.org/format/#document-resource-object-relationships
* @see https://jsonapi.org/recommendations/#urls-relationships
*/
protected $context;
/**
* The data of the relationship object.
*
* @var \Drupal\jsonapi\JsonApiResource\RelationshipData
*/
protected $data;
/**
* The relationship's public field name.
*
* @var string
*/
protected $fieldName;
/**
* The relationship object's links.
*
* @var \Drupal\jsonapi\JsonApiResource\LinkCollection
*/
protected $links;
/**
* The relationship object's meta member.
*
* @var array
*/
protected $meta;
/**
* Relationship constructor.
*
* This constructor is protected by design. To create a new relationship, use
* static::createFromEntityReferenceField().
*
* @param string $public_field_name
* The public field name of the relationship field.
* @param \Drupal\jsonapi\JsonApiResource\RelationshipData $data
* The relationship data.
* @param \Drupal\jsonapi\JsonApiResource\LinkCollection $links
* Any links for the resource object, if a `self` link is not
* provided, one will be automatically added if the resource is locatable
* and is not internal.
* @param array $meta
* Any relationship metadata.
* @param \Drupal\jsonapi\JsonApiResource\ResourceObject $context
* The relationship's context resource object. Use the
* self::withContext() method to establish a context.
*
* @see \Drupal\jsonapi\JsonApiResource\Relationship::createFromEntityReferenceField()
*/
protected function __construct($public_field_name, RelationshipData $data, LinkCollection $links, array $meta, ResourceObject $context) {
$this->fieldName = $public_field_name;
$this->data = $data;
$this->links = $links->withContext($this);
$this->meta = $meta;
$this->context = $context;
}
/**
* Creates a new Relationship from an entity reference field.
*
* @param \Drupal\jsonapi\JsonApiResource\ResourceObject $context
* The context resource object of the relationship to be created.
* @param \Drupal\Core\Field\EntityReferenceFieldItemListInterface $field
* The entity reference field from which to create the relationship.
* @param \Drupal\jsonapi\JsonApiResource\LinkCollection $links
* (optional) Any extra links for the Relationship, if a `self` link is not
* provided, one will be automatically added if the context resource is
* locatable and is not internal.
* @param array $meta
* (optional) Any relationship metadata.
*
* @return static
* An instantiated relationship object.
*/
public static function createFromEntityReferenceField(ResourceObject $context, EntityReferenceFieldItemListInterface $field, ?LinkCollection $links = NULL, array $meta = []) {
$context_resource_type = $context->getResourceType();
$resource_field = $context_resource_type->getFieldByInternalName($field->getName());
return new static($resource_field->getPublicName(), new RelationshipData(ResourceIdentifier::toResourceIdentifiers($field), $resource_field->hasOne() ? 1 : -1), static::buildLinkCollectionFromEntityReferenceField($context, $field, $links ?: new LinkCollection([])), $meta, $context);
}
/**
* Gets context resource object of the relationship.
*
* @return \Drupal\jsonapi\JsonApiResource\ResourceObject
* The context ResourceObject.
*
* @see \Drupal\jsonapi\JsonApiResource\Relationship::$context
*/
public function getContext() {
return $this->context;
}
/**
* Gets the relationship object's public field name.
*
* @return string
* The relationship's field name.
*/
public function getFieldName() {
return $this->fieldName;
}
/**
* Gets the relationship object's data.
*
* @return \Drupal\jsonapi\JsonApiResource\RelationshipData
* The relationship's data.
*/
public function getData() {
return $this->data;
}
/**
* Gets the relationship object's links.
*
* @return \Drupal\jsonapi\JsonApiResource\LinkCollection
* The relationship object's links.
*/
public function getLinks() {
return $this->links;
}
/**
* Gets the relationship object's metadata.
*
* @return array
* The relationship object's metadata.
*/
public function getMeta() {
return $this->meta;
}
/**
* {@inheritdoc}
*/
public function getOmissions() {
return new OmittedData([]);
}
/**
* {@inheritdoc}
*/
public function getMergedLinks(LinkCollection $top_level_links) {
// When directly fetching a relationship object, the relationship object's
// links become the top-level object's links unless they've been
// overridden. Overrides are especially important for the `self` link, which
// must match the link that generated the response. For example, the
// top-level `self` link might have an `include` query parameter that would
// be lost otherwise.
// See https://jsonapi.org/format/#fetching-relationships-responses-200 and
// https://jsonapi.org/format/#document-top-level.
return LinkCollection::merge($top_level_links, $this->getLinks()
->filter(function ($key) use ($top_level_links) {
return !$top_level_links->hasLinkWithKey($key);
})
->withContext($top_level_links->getContext()));
}
/**
* {@inheritdoc}
*/
public function getMergedMeta(array $top_level_meta) {
return NestedArray::mergeDeep($top_level_meta, $this->getMeta());
}
/**
* Builds a LinkCollection for the given entity reference field.
*
* @param \Drupal\jsonapi\JsonApiResource\ResourceObject $context
* The context resource object of the relationship object.
* @param \Drupal\Core\Field\EntityReferenceFieldItemListInterface $field
* The entity reference field from which to create the links.
* @param \Drupal\jsonapi\JsonApiResource\LinkCollection $links
* Any extra links for the Relationship, if a `self` link is not provided,
* one will be automatically added if the context resource is locatable and
* is not internal.
*
* @return \Drupal\jsonapi\JsonApiResource\LinkCollection
* The built links.
*/
protected static function buildLinkCollectionFromEntityReferenceField(ResourceObject $context, EntityReferenceFieldItemListInterface $field, LinkCollection $links) {
$context_resource_type = $context->getResourceType();
$public_field_name = $context_resource_type->getPublicName($field->getName());
if ($context_resource_type->isLocatable() && !$context_resource_type->isInternal()) {
$context_is_versionable = $context_resource_type->isVersionable();
if (!$links->hasLinkWithKey('self')) {
$route_name = Routes::getRouteName($context_resource_type, "{$public_field_name}.relationship.get");
$self_link = Url::fromRoute($route_name, [
'entity' => $context->getId(),
]);
if ($context_is_versionable) {
$self_link->setOption('query', [
JsonApiSpec::VERSION_QUERY_PARAMETER => $context->getVersionIdentifier(),
]);
}
$links = $links->withLink('self', new Link(new CacheableMetadata(), $self_link, 'self'));
}
$has_non_internal_resource_type = array_reduce($context_resource_type->getRelatableResourceTypesByField($public_field_name), function ($carry, ResourceType $target) {
return $carry ?: !$target->isInternal();
}, FALSE);
// If a `related` link was not provided, automatically generate one from
// the relationship object to the collection resource with all of the
// resources targeted by this relationship. However, that link should
// *not* be generated if all of the relatable resources are internal.
// That's because, in that case, a route will not exist for it.
if (!$links->hasLinkWithKey('related') && $has_non_internal_resource_type) {
$route_name = Routes::getRouteName($context_resource_type, "{$public_field_name}.related");
$related_link = Url::fromRoute($route_name, [
'entity' => $context->getId(),
]);
if ($context_is_versionable) {
$related_link->setOption('query', [
JsonApiSpec::VERSION_QUERY_PARAMETER => $context->getVersionIdentifier(),
]);
}
$links = $links->withLink('related', new Link(new CacheableMetadata(), $related_link, 'related'));
}
}
return $links;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title |
---|---|---|---|---|
Relationship::$context | protected | property | The context resource object of the relationship. | |
Relationship::$data | protected | property | The data of the relationship object. | |
Relationship::$fieldName | protected | property | The relationship's public field name. | |
Relationship::$links | protected | property | The relationship object's links. | |
Relationship::$meta | protected | property | The relationship object's meta member. | |
Relationship::buildLinkCollectionFromEntityReferenceField | protected static | function | Builds a LinkCollection for the given entity reference field. | |
Relationship::createFromEntityReferenceField | public static | function | Creates a new Relationship from an entity reference field. | |
Relationship::getContext | public | function | Gets context resource object of the relationship. | |
Relationship::getData | public | function | Gets the relationship object's data. | Overrides TopLevelDataInterface::getData |
Relationship::getFieldName | public | function | Gets the relationship object's public field name. | |
Relationship::getLinks | public | function | Gets the relationship object's links. | |
Relationship::getMergedLinks | public | function | Overrides TopLevelDataInterface::getMergedLinks | |
Relationship::getMergedMeta | public | function | Overrides TopLevelDataInterface::getMergedMeta | |
Relationship::getMeta | public | function | Gets the relationship object's metadata. | |
Relationship::getOmissions | public | function | Overrides TopLevelDataInterface::getOmissions | |
Relationship::__construct | protected | function | Relationship constructor. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.