comparison 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
comparison
equal deleted inserted replaced
4:a9cd425dd02b 5:12f9dff5fda9
1 <?php
2
3 namespace Drupal\jsonapi\JsonApiResource;
4
5 use Drupal\Component\Assertion\Inspector;
6 use Drupal\Core\Cache\CacheableDependencyInterface;
7 use Drupal\Core\Cache\CacheableDependencyTrait;
8 use Drupal\Core\Cache\CacheableMetadata;
9 use Drupal\Core\Url;
10
11 /**
12 * Represents an RFC8288 based link.
13 *
14 * @internal JSON:API maintains no PHP API. The API is the HTTP API. This class
15 * may change at any time and could break any dependencies on it.
16 *
17 * @see https://www.drupal.org/project/jsonapi/issues/3032787
18 * @see jsonapi.api.php
19 *
20 * @see https://tools.ietf.org/html/rfc8288
21 */
22 final class Link implements CacheableDependencyInterface {
23
24 use CacheableDependencyTrait;
25
26 /**
27 * The link URI.
28 *
29 * @var \Drupal\Core\Url
30 */
31 protected $uri;
32
33 /**
34 * The URI, as a string.
35 *
36 * @var string
37 */
38 protected $href;
39
40 /**
41 * The link relation types.
42 *
43 * @var string[]
44 */
45 protected $rel;
46
47 /**
48 * The link target attributes.
49 *
50 * @var string[]
51 * An associative array where the keys are the attribute keys and values are
52 * either string or an array of strings.
53 */
54 protected $attributes;
55
56 /**
57 * JSON:API Link constructor.
58 *
59 * @param \Drupal\Core\Cache\CacheableMetadata $cacheability
60 * Any cacheability metadata associated with the link. For example, a
61 * 'call-to-action' link might reference a registration resource if an event
62 * has vacancies or a wait-list resource otherwise. Therefore, the link's
63 * cacheability might be depend on a certain entity's values other than the
64 * entity on which the link will appear.
65 * @param \Drupal\Core\Url $url
66 * The Url object for the link.
67 * @param string[] $link_relation_types
68 * An array of registered or extension RFC8288 link relation types.
69 * @param array $target_attributes
70 * An associative array of target attributes for the link.
71 *
72 * @see https://tools.ietf.org/html/rfc8288#section-2.1
73 */
74 public function __construct(CacheableMetadata $cacheability, Url $url, array $link_relation_types, array $target_attributes = []) {
75 // @todo: uncomment the extra assertion below when JSON:API begins to use its own extension relation types.
76 assert(/* !empty($link_relation_types) && */Inspector::assertAllStrings($link_relation_types));
77 assert(Inspector::assertAllStrings(array_keys($target_attributes)));
78 assert(Inspector::assertAll(function ($target_attribute_value) {
79 return is_string($target_attribute_value)
80 || is_array($target_attribute_value)
81 && Inspector::assertAllStrings($target_attribute_value);
82 }, array_values($target_attributes)));
83 $generated_url = $url->setAbsolute()->toString(TRUE);
84 $this->href = $generated_url->getGeneratedUrl();
85 $this->uri = $url;
86 $this->rel = $link_relation_types;
87 $this->attributes = $target_attributes;
88 $this->setCacheability($cacheability->addCacheableDependency($generated_url));
89 }
90
91 /**
92 * Gets the link's URI.
93 *
94 * @return \Drupal\Core\Url
95 * The link's URI as a Url object.
96 */
97 public function getUri() {
98 return $this->uri;
99 }
100
101 /**
102 * Gets the link's URI as a string.
103 *
104 * @return string
105 * The link's URI as a string.
106 */
107 public function getHref() {
108 return $this->href;
109 }
110
111 /**
112 * Gets the link's relation types.
113 *
114 * @return string[]
115 * The link's relation types.
116 */
117 public function getLinkRelationTypes() {
118 return $this->rel;
119 }
120
121 /**
122 * Gets the link's target attributes.
123 *
124 * @return string[]
125 * The link's target attributes.
126 */
127 public function getTargetAttributes() {
128 return $this->attributes;
129 }
130
131 /**
132 * Compares two links by their href.
133 *
134 * @param \Drupal\jsonapi\JsonApiResource\Link $a
135 * The first link.
136 * @param \Drupal\jsonapi\JsonApiResource\Link $b
137 * The second link.
138 *
139 * @return int
140 * The result of strcmp() on the links' hrefs.
141 */
142 public static function compare(Link $a, Link $b) {
143 return strcmp($a->getHref(), $b->getHref());
144 }
145
146 /**
147 * Merges two link objects' relation types and target attributes.
148 *
149 * The links must share the same URI.
150 *
151 * @param \Drupal\jsonapi\JsonApiResource\Link $a
152 * The first link.
153 * @param \Drupal\jsonapi\JsonApiResource\Link $b
154 * The second link.
155 *
156 * @return static
157 * A new JSON:API Link object with the link relation type and target
158 * attributes merged.
159 */
160 public static function merge(Link $a, Link $b) {
161 assert(static::compare($a, $b) === 0);
162 $merged_rels = array_unique(array_merge($a->getLinkRelationTypes(), $b->getLinkRelationTypes()));
163 $merged_attributes = $a->getTargetAttributes();
164 foreach ($b->getTargetAttributes() as $key => $value) {
165 if (isset($merged_attributes[$key])) {
166 // The attribute values can be either a string or an array of strings.
167 $value = array_unique(array_merge(
168 is_string($merged_attributes[$key]) ? [$merged_attributes[$key]] : $merged_attributes[$key],
169 is_string($value) ? [$value] : $value
170 ));
171 }
172 $merged_attributes[$key] = count($value) === 1 ? reset($value) : $value;
173 }
174 $merged_cacheability = (new CacheableMetadata())->addCacheableDependency($a)->addCacheableDependency($b);
175 return new static($merged_cacheability, $a->getUri(), $merged_rels, $merged_attributes);
176 }
177
178 }