// since the "machine-name" target attribute is non-standard.
// See https://tools.ietf.org/html/draft-ietf-httpapi-linkset-08#section-4.2.4.3
return $target +
['machine-name' =>
[$menu_id]];
},
$target_objects);
} $linkset = !
empty($tree) ?
[['anchor' =>
$anchor] +
$links] :
[];
$data =
['linkset' =>
$linkset];
// Set the response content-type header.
$headers =
['content-type' => 'application/linkset+json'
];
$response =
new CacheableJsonResponse($data, 200,
$headers);
// Attach cacheability metadata to the response.
$response->
addCacheableDependency($cacheability);
return $response;
} /**
* Encode a menu tree as link items and capture any cacheability metadata.
*
* This method recursively traverses the given menu tree to produce a flat
* array of link items encoded according the application/linkset+json
* media type.
*
* To preserve hierarchical information, the target attribute contains a
* `hierarchy` member. Its value is an array containing the position of a link
* within a particular sub-tree prepended by the positions of its ancestors,
* and can be used to reconstruct a hierarchical data structure.
*
* The reason that a `hierarchy` member is used instead of a `parent` or
* `children` member is because it is more compact, more suited to the linkset
* media type, and because it simplifies many menu operations. Specifically:
*
* 1. Creating a `parent` member would require each link to have an `id`
* in order to have something referenceable by the `parent` member. Reusing
* the link plugin IDs would not be viable because it would leak
* information about which modules are installed on the site. Therefore,
* this ID would have to be invented and would probably end up looking a
* lot like the `hierarchy` value. Finally, link IDs would encourage
* clients to hardcode the ID instead of using link relation types
* appropriately.
* 2. The linkset media type is not itself hierarchical. This means that
* `children` is infeasible without inventing our own Drupal-specific media
* type.
* 3. The `hierarchy` member can be used to efficiently perform tree
* operations that would otherwise be more complicated to implement. For
* example, by comparing the first X amount of hierarchy levels, you can
* find any subtree without writing recursive logic or complicated loops.
* Visit the URL below for more examples.
*
* The structure of a `hierarchy` value is defined below.
*
* A link which is a child of another link will always be prefixed by the
* exact value of their parent's hierarchy member. For example, if a link /bar
* is a child of a link /foo and /foo has a hierarchy member with the value
* ["1"], then the link /bar might have a hierarchy member with the value
* ["1", "0"]. The link /foo can be said to have depth 1, while the link
* /bar can be said to have depth 2.
*
* Links which have the same parent (or no parent) have their relative order
* preserved in the final component of the hierarchy value.
*
* According to the Linkset specification, each value in the hierarchy array
* must be a string. See https://tools.ietf.org/html/draft-ietf-httpapi-linkset-08#section-4.2.4.3
*
* @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree
* A tree of menu elements.
* @param \Drupal\Core\Cache\RefinableCacheableDependencyInterface $cacheability
* An object to capture any cacheability metadata.
* @param array $hierarchy_ancestors
* (Internal use only) The hierarchy value of the parent element
* if $tree is a subtree. Do not pass this value.
*
* @return array
* An array which can be JSON-encoded to represent the given link tree.
*
* @see https://www.drupal.org/project/decoupled_menus/issues/3204132#comment-14439385
*/