function IncludeResolver::resolveIncludeTree
Same name in other branches
- 9 core/modules/jsonapi/src/IncludeResolver.php \Drupal\jsonapi\IncludeResolver::resolveIncludeTree()
- 8.9.x core/modules/jsonapi/src/IncludeResolver.php \Drupal\jsonapi\IncludeResolver::resolveIncludeTree()
- 11.x core/modules/jsonapi/src/IncludeResolver.php \Drupal\jsonapi\IncludeResolver::resolveIncludeTree()
Receives a tree of include field names and resolves resources for it.
This method takes a tree of relationship field names and JSON:API Data object. For the top-level of the tree and for each entity in the collection, it gets the target entity type and IDs for each relationship field. The method then loads all of those targets and calls itself recursively with the next level of the tree and those loaded resources.
Parameters
array $include_tree: The include paths, represented as a tree.
\Drupal\jsonapi\JsonApiResource\Data $data: The entity collection from which includes should be resolved.
\Drupal\jsonapi\JsonApiResource\Data|null $includes: (Internal use only) Any prior resolved includes.
Return value
\Drupal\jsonapi\JsonApiResource\Data A JSON:API Data of included items.
Throws
\Drupal\Component\Plugin\Exception\PluginNotFoundException Thrown if an included entity type doesn't exist.
\Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException Thrown if a storage handler couldn't be loaded.
1 call to IncludeResolver::resolveIncludeTree()
- IncludeResolver::resolve in core/
modules/ jsonapi/ src/ IncludeResolver.php - Resolves included resources.
File
-
core/
modules/ jsonapi/ src/ IncludeResolver.php, line 102
Class
- IncludeResolver
- Resolves included resources for an entity or collection of entities.
Namespace
Drupal\jsonapiCode
protected function resolveIncludeTree(array $include_tree, Data $data, ?Data $includes = NULL) {
$includes = is_null($includes) ? new IncludedData([]) : $includes;
foreach ($include_tree as $field_name => $children) {
$references = [];
foreach ($data as $resource_object) {
// Some objects in the collection may be LabelOnlyResourceObjects or
// EntityAccessDeniedHttpException objects.
assert($resource_object instanceof ResourceIdentifierInterface);
$public_field_name = $resource_object->getResourceType()
->getPublicName($field_name);
if ($resource_object instanceof LabelOnlyResourceObject) {
$message = "The current user is not allowed to view this relationship.";
$exception = new EntityAccessDeniedHttpException($resource_object->getEntity(), AccessResult::forbidden("The user only has authorization for the 'view label' operation."), '', $message, $public_field_name);
$includes = IncludedData::merge($includes, new IncludedData([
$exception,
]));
continue;
}
elseif (!$resource_object instanceof ResourceObject) {
continue;
}
// Not all entities in $entity_collection will be of the same bundle and
// may not have all of the same fields. Therefore, calling
// $resource_object->get($a_missing_field_name) will result in an
// exception.
if (!$resource_object->hasField($public_field_name)) {
continue;
}
$field_list = $resource_object->getField($public_field_name);
// Config entities don't have real fields and can't have relationships.
if (!$field_list instanceof FieldItemListInterface) {
continue;
}
$field_access = $field_list->access('view', NULL, TRUE);
if (!$field_access->isAllowed()) {
$message = 'The current user is not allowed to view this relationship.';
$exception = new EntityAccessDeniedHttpException($field_list->getEntity(), $field_access, '', $message, $public_field_name);
$includes = IncludedData::merge($includes, new IncludedData([
$exception,
]));
continue;
}
if (is_subclass_of($field_list->getItemDefinition()
->getClass(), EntityReferenceItemInterface::class)) {
foreach ($field_list as $field_item) {
if (!$field_item->getDataDefinition()
->getPropertyDefinition('entity') instanceof DataReferenceDefinitionInterface) {
continue;
}
if (!$field_item->entity instanceof EntityInterface) {
continue;
}
// Support entity reference fields that don't have the referenced
// target type stored in settings.
$references[$field_item->entity
->getEntityTypeId()][] = $field_item->get($field_item::mainPropertyName())
->getValue();
}
}
else {
@trigger_error(sprintf('Entity reference field items not implementing %s is deprecated in drupal:10.2.0 and will be required in drupal:11.0.0. See https://www.drupal.org/node/3279140', EntityReferenceItemInterface::class), E_USER_DEPRECATED);
$target_type = $field_list->getFieldDefinition()
->getFieldStorageDefinition()
->getSetting('target_type');
if (!empty($target_type)) {
foreach ($field_list as $field_item) {
$references[$target_type][] = $field_item->get($field_item::mainPropertyName())
->getValue();
}
}
}
}
foreach ($references as $target_type => $ids) {
$entity_storage = $this->entityTypeManager
->getStorage($target_type);
$targeted_entities = $entity_storage->loadMultiple(array_unique($ids));
$access_checked_entities = array_map(function (EntityInterface $entity) {
return $this->entityAccessChecker
->getAccessCheckedResourceObject($entity);
}, $targeted_entities);
$targeted_collection = new IncludedData(array_filter($access_checked_entities, function (ResourceIdentifierInterface $resource_object) {
return !$resource_object->getResourceType()
->isInternal();
}));
$includes = static::resolveIncludeTree($children, $targeted_collection, IncludedData::merge($includes, $targeted_collection));
}
}
return $includes;
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.