public static function FieldResolver::resolveInternalIncludePath in JSON:API 8
Same name and namespace in other branches
- 8.2 src/Context/FieldResolver.php \Drupal\jsonapi\Context\FieldResolver::resolveInternalIncludePath()
Validates and resolves an include path into its internal possibilities.
Each resource type may define its own external names for its internal field names. As a result, a single external include path may target multiple internal paths.
This can happen when an entity reference field has different allowed entity types *per bundle* (as is possible with comment entities) or when different resource types share an external field name but resolve to different internal fields names.
Example 1: An installation may have three comment types for three different entity types, two of which have a file field and one of which does not. In that case, a path like
field_comments . entity_id . media;
might be resolved to both
field_comments . entity_id . field_audio;
and
field_comments . entity_id . field_image;
.
Example 2: A path of
field_author_profile . account;
might resolve to
field_author_profile . uid;
and
field_author_profile . field_user;
if
field_author_profile;
can relate to two different JSON API resource types (like `node--profile` and `node--migrated_profile`) which have the external field name
account;
aliased to different internal field names.
Parameters
\Drupal\jsonapi\ResourceType\ResourceType $resource_type: The resource type for which the path should be validated.
string[] $path_parts: The include path as an array of strings. For example, the include query parameter string of
field_tags . uid;
should be given as
[
'field_tags',
'uid',
];
.
int $depth: (internal) Used to track recursion depth in order to generate better exception messages.
Return value
string[] The resolved internal include paths.
Throws
\Symfony\Component\HttpKernel\Exception\BadRequestHttpException Thrown if the path contains invalid specifiers.
1 call to FieldResolver::resolveInternalIncludePath()
- JsonApiDocumentTopLevelNormalizer::expandContext in src/
Normalizer/ JsonApiDocumentTopLevelNormalizer.php - Expand the context information based on the current request context.
File
- src/
Context/ FieldResolver.php, line 169
Class
- FieldResolver
- A service that evaluates external path expressions against Drupal fields.
Namespace
Drupal\jsonapi\ContextCode
public static function resolveInternalIncludePath(ResourceType $resource_type, array $path_parts, $depth = 0) {
if (empty($path_parts)) {
throw new BadRequestHttpException('Empty include path.');
}
$internal_field_name = $resource_type
->getInternalName($path_parts[0]);
$relatable_resource_types = $resource_type
->getRelatableResourceTypesByField($internal_field_name);
if (empty($relatable_resource_types)) {
$message = "`{$internal_field_name}` is not a valid relationship field name.";
if (!empty($possible = implode(', ', array_keys($resource_type
->getRelatableResourceTypes())))) {
$message .= " Possible values: {$possible}.";
}
throw new BadRequestHttpException($message);
}
$remaining_parts = array_slice($path_parts, 1);
if (empty($remaining_parts)) {
return [
[
$internal_field_name,
],
];
}
$exceptions = [];
$resolved = [];
foreach ($relatable_resource_types as $relatable_resource_type) {
try {
// Each resource type may resolve the path differently and may return
// multiple possible resolutions.
$resolved += static::resolveInternalIncludePath($relatable_resource_type, $remaining_parts, $depth + 1);
} catch (BadRequestHttpException $e) {
$exceptions[] = $e;
}
}
if (!empty($exceptions) && count($exceptions) === count($relatable_resource_types)) {
$previous_messages = implode(' ', array_unique(array_map(function (BadRequestHttpException $e) {
return $e
->getMessage();
}, $exceptions)));
// Only add the full include path on the first level of recursion so that
// the invalid path phrase isn't repeated at every level.
throw new BadRequestHttpException($depth === 0 ? sprintf("`%s` is not a valid include path. {$previous_messages}", implode('.', $path_parts)) : $previous_messages);
}
// The resolved internal paths do not include the current field name because
// resolution happens in a recursive process.
return array_map(function ($possibility) use ($internal_field_name) {
return array_merge([
$internal_field_name,
], $possibility);
}, $resolved);
}