Mercurial > hg > isophonics-drupal-site
comparison core/modules/jsonapi/src/JsonApiResource/LinkCollection.php @ 18:af1871eacc83
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:33:08 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
17:129ea1e6d783 | 18:af1871eacc83 |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\jsonapi\JsonApiResource; | |
4 | |
5 use Drupal\Component\Assertion\Inspector; | |
6 | |
7 /** | |
8 * Contains a set of JSON:API Link objects. | |
9 * | |
10 * @internal JSON:API maintains no PHP API. The API is the HTTP API. This class | |
11 * may change at any time and could break any dependencies on it. | |
12 * | |
13 * @see https://www.drupal.org/project/jsonapi/issues/3032787 | |
14 * @see jsonapi.api.php | |
15 */ | |
16 final class LinkCollection implements \IteratorAggregate { | |
17 | |
18 /** | |
19 * The links in the collection, keyed by unique strings. | |
20 * | |
21 * @var \Drupal\jsonapi\JsonApiResource\Link[] | |
22 */ | |
23 protected $links; | |
24 | |
25 /** | |
26 * The link context. | |
27 * | |
28 * All links objects exist within a context object. Links form a relationship | |
29 * between a source IRI and target IRI. A context is the link's source. | |
30 * | |
31 * @var \Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel|\Drupal\jsonapi\JsonApiResource\ResourceObject | |
32 * | |
33 * @see https://tools.ietf.org/html/rfc8288#section-3.2 | |
34 */ | |
35 protected $context; | |
36 | |
37 /** | |
38 * LinkCollection constructor. | |
39 * | |
40 * @param \Drupal\jsonapi\JsonApiResource\Link[] $links | |
41 * An associated array of key names and JSON:API Link objects. | |
42 * @param \Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel|\Drupal\jsonapi\JsonApiResource\ResourceObject $context | |
43 * (internal use only) The context object. Use the self::withContext() | |
44 * method to establish a context. This should be done automatically when | |
45 * a LinkCollection is passed into a context object. | |
46 */ | |
47 public function __construct(array $links, $context = NULL) { | |
48 assert(Inspector::assertAll(function ($key) { | |
49 return static::validKey($key); | |
50 }, array_keys($links))); | |
51 assert(Inspector::assertAll(function ($link) { | |
52 return $link instanceof Link || is_array($link) && Inspector::assertAllObjects($link, Link::class); | |
53 }, $links)); | |
54 assert(is_null($context) || Inspector::assertAllObjects([$context], JsonApiDocumentTopLevel::class, ResourceObject::class)); | |
55 ksort($links); | |
56 $this->links = array_map(function ($link) { | |
57 return is_array($link) ? $link : [$link]; | |
58 }, $links); | |
59 $this->context = $context; | |
60 } | |
61 | |
62 /** | |
63 * {@inheritdoc} | |
64 */ | |
65 public function getIterator() { | |
66 assert(!is_null($this->context), 'A LinkCollection is invalid unless a context has been established.'); | |
67 return new \ArrayIterator($this->links); | |
68 } | |
69 | |
70 /** | |
71 * Gets a new LinkCollection with the given link inserted. | |
72 * | |
73 * @param string $key | |
74 * A key for the link. If the key already exists and the link shares an href | |
75 * with an existing link with that key, those links will be merged together. | |
76 * @param \Drupal\jsonapi\JsonApiResource\Link $new_link | |
77 * The link to insert. | |
78 * | |
79 * @return static | |
80 * A new LinkCollection with the given link inserted or merged with the | |
81 * current set of links. | |
82 */ | |
83 public function withLink($key, Link $new_link) { | |
84 assert(static::validKey($key)); | |
85 $merged = $this->links; | |
86 if (isset($merged[$key])) { | |
87 foreach ($merged[$key] as $index => $existing_link) { | |
88 if (Link::compare($existing_link, $new_link) === 0) { | |
89 $merged[$key][$index] = Link::merge($existing_link, $new_link); | |
90 return new static($merged, $this->context); | |
91 } | |
92 } | |
93 } | |
94 $merged[$key][] = $new_link; | |
95 return new static($merged, $this->context); | |
96 } | |
97 | |
98 /** | |
99 * Whether a link with the given key exists. | |
100 * | |
101 * @param string $key | |
102 * The key. | |
103 * | |
104 * @return bool | |
105 * TRUE if a link with the given key exist, FALSE otherwise. | |
106 */ | |
107 public function hasLinkWithKey($key) { | |
108 return array_key_exists($key, $this->links); | |
109 } | |
110 | |
111 /** | |
112 * Establishes a new context for a LinkCollection. | |
113 * | |
114 * @param \Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel|\Drupal\jsonapi\JsonApiResource\ResourceObject $context | |
115 * The new context object. | |
116 * | |
117 * @return static | |
118 * A new LinkCollection with the given context. | |
119 */ | |
120 public function withContext($context) { | |
121 return new static($this->links, $context); | |
122 } | |
123 | |
124 /** | |
125 * Gets the LinkCollection's context object. | |
126 * | |
127 * @return \Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel|\Drupal\jsonapi\JsonApiResource\ResourceObject | |
128 * The LinkCollection's context. | |
129 */ | |
130 public function getContext() { | |
131 assert(!is_null($this->context), 'A LinkCollection is invalid unless a context has been established.'); | |
132 return $this->context; | |
133 } | |
134 | |
135 /** | |
136 * Filters a LinkCollection using the provided callback. | |
137 * | |
138 * @param callable $f | |
139 * The filter callback. The callback has the signature below. | |
140 * | |
141 * @code | |
142 * boolean callback(string $key, \Drupal\jsonapi\JsonApiResource\Link $link, mixed $context)) | |
143 * @endcode | |
144 * | |
145 * @return \Drupal\jsonapi\JsonApiResource\LinkCollection | |
146 * A new, filtered LinkCollection. | |
147 */ | |
148 public function filter(callable $f) { | |
149 $links = iterator_to_array($this); | |
150 $filtered = array_reduce(array_keys($links), function ($filtered, $key) use ($links, $f) { | |
151 if ($f($key, $links[$key], $this->context)) { | |
152 $filtered[$key] = $links[$key]; | |
153 } | |
154 return $filtered; | |
155 }, []); | |
156 return new LinkCollection($filtered, $this->context); | |
157 } | |
158 | |
159 /** | |
160 * Merges two LinkCollections. | |
161 * | |
162 * @param \Drupal\jsonapi\JsonApiResource\LinkCollection $a | |
163 * The first link collection. | |
164 * @param \Drupal\jsonapi\JsonApiResource\LinkCollection $b | |
165 * The second link collection. | |
166 * | |
167 * @return \Drupal\jsonapi\JsonApiResource\LinkCollection | |
168 * A new LinkCollection with the links of both inputs. | |
169 */ | |
170 public static function merge(LinkCollection $a, LinkCollection $b) { | |
171 assert($a->getContext() === $b->getContext()); | |
172 $merged = new LinkCollection([], $a->getContext()); | |
173 foreach ($a as $key => $links) { | |
174 $merged = array_reduce($links, function (self $merged, Link $link) use ($key) { | |
175 return $merged->withLink($key, $link); | |
176 }, $merged); | |
177 } | |
178 foreach ($b as $key => $links) { | |
179 $merged = array_reduce($links, function (self $merged, Link $link) use ($key) { | |
180 return $merged->withLink($key, $link); | |
181 }, $merged); | |
182 } | |
183 return $merged; | |
184 } | |
185 | |
186 /** | |
187 * Ensures that a link key is valid. | |
188 * | |
189 * @param string $key | |
190 * A key name. | |
191 * | |
192 * @return bool | |
193 * TRUE if the key is valid, FALSE otherwise. | |
194 */ | |
195 protected static function validKey($key) { | |
196 return is_string($key) && !is_numeric($key) && strpos($key, ':') === FALSE; | |
197 } | |
198 | |
199 } |