Mercurial > hg > cmmr2012-drupal-site
diff core/modules/jsonapi/src/JsonApiResource/Link.php @ 5:12f9dff5fda9 tip
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:34:47 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/jsonapi/src/JsonApiResource/Link.php Thu May 09 15:34:47 2019 +0100 @@ -0,0 +1,178 @@ +<?php + +namespace Drupal\jsonapi\JsonApiResource; + +use Drupal\Component\Assertion\Inspector; +use Drupal\Core\Cache\CacheableDependencyInterface; +use Drupal\Core\Cache\CacheableDependencyTrait; +use Drupal\Core\Cache\CacheableMetadata; +use Drupal\Core\Url; + +/** + * Represents an RFC8288 based link. + * + * @internal JSON:API maintains no PHP API. The API is the HTTP API. This class + * may change at any time and could break any dependencies on it. + * + * @see https://www.drupal.org/project/jsonapi/issues/3032787 + * @see jsonapi.api.php + * + * @see https://tools.ietf.org/html/rfc8288 + */ +final class Link implements CacheableDependencyInterface { + + use CacheableDependencyTrait; + + /** + * The link URI. + * + * @var \Drupal\Core\Url + */ + protected $uri; + + /** + * The URI, as a string. + * + * @var string + */ + protected $href; + + /** + * The link relation types. + * + * @var string[] + */ + protected $rel; + + /** + * The link target attributes. + * + * @var string[] + * An associative array where the keys are the attribute keys and values are + * either string or an array of strings. + */ + protected $attributes; + + /** + * JSON:API Link constructor. + * + * @param \Drupal\Core\Cache\CacheableMetadata $cacheability + * Any cacheability metadata associated with the link. For example, a + * 'call-to-action' link might reference a registration resource if an event + * has vacancies or a wait-list resource otherwise. Therefore, the link's + * cacheability might be depend on a certain entity's values other than the + * entity on which the link will appear. + * @param \Drupal\Core\Url $url + * The Url object for the link. + * @param string[] $link_relation_types + * An array of registered or extension RFC8288 link relation types. + * @param array $target_attributes + * An associative array of target attributes for the link. + * + * @see https://tools.ietf.org/html/rfc8288#section-2.1 + */ + public function __construct(CacheableMetadata $cacheability, Url $url, array $link_relation_types, array $target_attributes = []) { + // @todo: uncomment the extra assertion below when JSON:API begins to use its own extension relation types. + assert(/* !empty($link_relation_types) && */Inspector::assertAllStrings($link_relation_types)); + assert(Inspector::assertAllStrings(array_keys($target_attributes))); + assert(Inspector::assertAll(function ($target_attribute_value) { + return is_string($target_attribute_value) + || is_array($target_attribute_value) + && Inspector::assertAllStrings($target_attribute_value); + }, array_values($target_attributes))); + $generated_url = $url->setAbsolute()->toString(TRUE); + $this->href = $generated_url->getGeneratedUrl(); + $this->uri = $url; + $this->rel = $link_relation_types; + $this->attributes = $target_attributes; + $this->setCacheability($cacheability->addCacheableDependency($generated_url)); + } + + /** + * Gets the link's URI. + * + * @return \Drupal\Core\Url + * The link's URI as a Url object. + */ + public function getUri() { + return $this->uri; + } + + /** + * Gets the link's URI as a string. + * + * @return string + * The link's URI as a string. + */ + public function getHref() { + return $this->href; + } + + /** + * Gets the link's relation types. + * + * @return string[] + * The link's relation types. + */ + public function getLinkRelationTypes() { + return $this->rel; + } + + /** + * Gets the link's target attributes. + * + * @return string[] + * The link's target attributes. + */ + public function getTargetAttributes() { + return $this->attributes; + } + + /** + * Compares two links by their href. + * + * @param \Drupal\jsonapi\JsonApiResource\Link $a + * The first link. + * @param \Drupal\jsonapi\JsonApiResource\Link $b + * The second link. + * + * @return int + * The result of strcmp() on the links' hrefs. + */ + public static function compare(Link $a, Link $b) { + return strcmp($a->getHref(), $b->getHref()); + } + + /** + * Merges two link objects' relation types and target attributes. + * + * The links must share the same URI. + * + * @param \Drupal\jsonapi\JsonApiResource\Link $a + * The first link. + * @param \Drupal\jsonapi\JsonApiResource\Link $b + * The second link. + * + * @return static + * A new JSON:API Link object with the link relation type and target + * attributes merged. + */ + public static function merge(Link $a, Link $b) { + assert(static::compare($a, $b) === 0); + $merged_rels = array_unique(array_merge($a->getLinkRelationTypes(), $b->getLinkRelationTypes())); + $merged_attributes = $a->getTargetAttributes(); + foreach ($b->getTargetAttributes() as $key => $value) { + if (isset($merged_attributes[$key])) { + // The attribute values can be either a string or an array of strings. + $value = array_unique(array_merge( + is_string($merged_attributes[$key]) ? [$merged_attributes[$key]] : $merged_attributes[$key], + is_string($value) ? [$value] : $value + )); + } + $merged_attributes[$key] = count($value) === 1 ? reset($value) : $value; + } + $merged_cacheability = (new CacheableMetadata())->addCacheableDependency($a)->addCacheableDependency($b); + return new static($merged_cacheability, $a->getUri(), $merged_rels, $merged_attributes); + } + +}