Skip to content

Commit 9912f7a

Browse files
authored
feat(api): Resolve links (#55)
1 parent 745ec86 commit 9912f7a

File tree

8 files changed

+811
-21
lines changed

8 files changed

+811
-21
lines changed

src/Request/StoryRequest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
use Storyblok\Api\Domain\Value\Dto\Version;
1818
use Storyblok\Api\Domain\Value\Resolver\RelationCollection;
19+
use Storyblok\Api\Domain\Value\Resolver\ResolveLinks;
1920
use Webmozart\Assert\Assert;
2021

2122
/**
@@ -27,6 +28,7 @@ public function __construct(
2728
public string $language = 'default',
2829
public ?Version $version = null,
2930
public RelationCollection $withRelations = new RelationCollection(),
31+
public ResolveLinks $resolveLinks = new ResolveLinks(),
3032
) {
3133
Assert::stringNotEmpty($language);
3234
}
@@ -36,6 +38,8 @@ public function __construct(
3638
* language: string,
3739
* version?: string,
3840
* resolve_relations?: string,
41+
* resolve_links?: string,
42+
* resolve_links_level?: int,
3943
* }
4044
*/
4145
public function toArray(): array
@@ -52,6 +56,11 @@ public function toArray(): array
5256
$array['resolve_relations'] = $this->withRelations->toString();
5357
}
5458

59+
if (null !== $this->resolveLinks->type) {
60+
$array['resolve_links'] = $this->resolveLinks->type->value;
61+
$array['resolve_links_level'] = $this->resolveLinks->level->value;
62+
}
63+
5564
return $array;
5665
}
5766
}

src/Resolver/StoryResolver.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,10 @@ public function resolve(array $target, array $relations): array
2525
{
2626
$relationMap = [];
2727

28-
foreach ($relations as $key => $relation) {
28+
foreach ($relations as $relation) {
2929
Assert::keyExists($relation, 'uuid');
3030
Assert::uuid($relation['uuid']);
3131
$relationMap[$relation['uuid']] = $relation;
32-
33-
// There is a limit of possible resolvable relations.
34-
// @see https://www.storyblok.com/docs/api/content-delivery/v2/stories/retrieve-a-single-story
35-
if (50 === $key) {
36-
break;
37-
}
3832
}
3933

4034
foreach ($target as &$value) {
@@ -44,6 +38,12 @@ public function resolve(array $target, array $relations): array
4438
continue;
4539
}
4640

41+
if (\is_array($value) && \array_key_exists('id', $value) && \array_key_exists($value['id'], $relationMap)) {
42+
$value = $relationMap[$value['id']];
43+
44+
continue;
45+
}
46+
4747
if (\is_array($value)) {
4848
$value = $this->resolve($value, $relations);
4949
}

src/Response/StoriesResponse.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
public array $rels;
3636

3737
/**
38-
* @var list<string>
38+
* @var list<array<string, mixed>>
3939
*/
4040
public array $links;
4141

src/Response/StoryResponse.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
public array $rels;
3434

3535
/**
36-
* @var list<array<mixed>>
36+
* @var list<array<string, mixed>>
3737
*/
3838
public array $links;
3939

src/StoriesResolvedApi.php

Lines changed: 171 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
namespace Storyblok\Api;
1616

1717
use Storyblok\Api\Domain\Value\Id;
18+
use Storyblok\Api\Domain\Value\Resolver\LinkType;
1819
use Storyblok\Api\Domain\Value\Uuid;
1920
use Storyblok\Api\Request\StoriesRequest;
2021
use Storyblok\Api\Request\StoryRequest;
@@ -30,21 +31,48 @@
3031
public function __construct(
3132
private StoriesApiInterface $storiesApi,
3233
private ResolverInterface $resolver,
34+
private bool $resolveRelations = false,
35+
private bool $resolveLinks = false,
3336
) {
3437
}
3538

3639
public function all(?StoriesRequest $request = null): StoriesResponse
3740
{
3841
$response = $this->storiesApi->all($request);
3942

40-
if (null === $request || 0 === $request->withRelations->count()) {
43+
if (null === $request) {
4144
return $response;
4245
}
4346

4447
$stories = [];
4548

4649
foreach ($response->stories as $story) {
47-
$stories[] = $this->resolver->resolve($story, $response->rels);
50+
$resolvedStory = $story;
51+
52+
if ($this->resolveRelations && 0 !== $request->withRelations->count()) {
53+
/**
54+
* There is a limit of possible resolvable relations.
55+
*
56+
* @see https://www.storyblok.com/docs/api/content-delivery/v2/stories/retrieve-a-single-story
57+
*/
58+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->rels, 0, 50));
59+
}
60+
61+
if ($this->resolveLinks && null !== $request->resolveLinks->type) {
62+
/**
63+
* There is a limit of possible resolvable relations.
64+
*
65+
* @see https://www.storyblok.com/docs/guide/in-depth/rendering-the-link-field
66+
*/
67+
$limit = match ($request->resolveLinks->type) {
68+
LinkType::Story => 50,
69+
LinkType::Link, LinkType::Url => 500,
70+
};
71+
72+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->links, 0, $limit));
73+
}
74+
75+
$stories[] = $resolvedStory;
4876
}
4977

5078
return new StoriesResponse(
@@ -63,14 +91,39 @@ public function allByContentType(string $contentType, ?StoriesRequest $request =
6391
{
6492
$response = $this->storiesApi->allByContentType($contentType, $request);
6593

66-
if (null === $request || 0 === $request->withRelations->count()) {
94+
if (null === $request) {
6795
return $response;
6896
}
6997

7098
$stories = [];
7199

72100
foreach ($response->stories as $story) {
73-
$stories[] = $this->resolver->resolve($story, $response->rels);
101+
$resolvedStory = $story;
102+
103+
if ($this->resolveRelations && 0 !== $request->withRelations->count()) {
104+
/**
105+
* There is a limit of possible resolvable relations.
106+
*
107+
* @see https://www.storyblok.com/docs/api/content-delivery/v2/stories/retrieve-a-single-story
108+
*/
109+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->rels, 0, 50));
110+
}
111+
112+
if ($this->resolveLinks && null !== $request->resolveLinks->type) {
113+
/**
114+
* There is a limit of possible resolvable relations.
115+
*
116+
* @see https://www.storyblok.com/docs/guide/in-depth/rendering-the-link-field
117+
*/
118+
$limit = match ($request->resolveLinks->type) {
119+
LinkType::Story => 50,
120+
LinkType::Link, LinkType::Url => 500,
121+
};
122+
123+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->links, 0, $limit));
124+
}
125+
126+
$stories[] = $resolvedStory;
74127
}
75128

76129
return new StoriesResponse(
@@ -89,14 +142,39 @@ public function allByUuids(array $uuids, bool $keepOrder = true, ?StoriesRequest
89142
{
90143
$response = $this->storiesApi->allByUuids($uuids, $keepOrder, $request);
91144

92-
if (null === $request || 0 === $request->withRelations->count()) {
145+
if (null === $request) {
93146
return $response;
94147
}
95148

96149
$stories = [];
97150

98151
foreach ($response->stories as $story) {
99-
$stories[] = $this->resolver->resolve($story, $response->rels);
152+
$resolvedStory = $story;
153+
154+
if ($this->resolveRelations && 0 !== $request->withRelations->count()) {
155+
/**
156+
* There is a limit of possible resolvable relations.
157+
*
158+
* @see https://www.storyblok.com/docs/api/content-delivery/v2/stories/retrieve-a-single-story
159+
*/
160+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->rels, 0, 50));
161+
}
162+
163+
if ($this->resolveLinks && null !== $request->resolveLinks->type) {
164+
/**
165+
* There is a limit of possible resolvable relations.
166+
*
167+
* @see https://www.storyblok.com/docs/guide/in-depth/rendering-the-link-field
168+
*/
169+
$limit = match ($request->resolveLinks->type) {
170+
LinkType::Story => 50,
171+
LinkType::Link, LinkType::Url => 500,
172+
};
173+
174+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->links, 0, $limit));
175+
}
176+
177+
$stories[] = $resolvedStory;
100178
}
101179

102180
return new StoriesResponse(
@@ -115,41 +193,122 @@ public function bySlug(string $slug, ?StoryRequest $request = null): StoryRespon
115193
{
116194
$response = $this->storiesApi->bySlug($slug, $request);
117195

118-
$story = $this->resolver->resolve($response->story, $response->rels);
196+
if (null === $request) {
197+
return $response;
198+
}
199+
200+
$resolvedStory = $response->story;
201+
202+
if ($this->resolveRelations && 0 !== $request->withRelations->count()) {
203+
/**
204+
* There is a limit of possible resolvable relations.
205+
*
206+
* @see https://www.storyblok.com/docs/api/content-delivery/v2/stories/retrieve-a-single-story
207+
*/
208+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->rels, 0, 50));
209+
}
210+
211+
if ($this->resolveLinks && null !== $request->resolveLinks->type) {
212+
/**
213+
* There is a limit of possible resolvable relations.
214+
*
215+
* @see https://www.storyblok.com/docs/guide/in-depth/rendering-the-link-field
216+
*/
217+
$limit = match ($request->resolveLinks->type) {
218+
LinkType::Story => 50,
219+
LinkType::Link, LinkType::Url => 500,
220+
};
221+
222+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->links, 0, $limit));
223+
}
119224

120225
return new StoryResponse([
121226
'cv' => $response->cv,
122227
'rels' => $response->rels,
123228
'links' => $response->links,
124-
'story' => $story,
229+
'story' => $resolvedStory,
125230
]);
126231
}
127232

128233
public function byUuid(Uuid $uuid, ?StoryRequest $request = null): StoryResponse
129234
{
130235
$response = $this->storiesApi->byUuid($uuid, $request);
131236

132-
$story = $this->resolver->resolve($response->story, $response->rels);
237+
if (null === $request) {
238+
return $response;
239+
}
240+
241+
$resolvedStory = $response->story;
242+
243+
if ($this->resolveRelations && 0 !== $request->withRelations->count()) {
244+
/**
245+
* There is a limit of possible resolvable relations.
246+
*
247+
* @see https://www.storyblok.com/docs/api/content-delivery/v2/stories/retrieve-a-single-story
248+
*/
249+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->rels, 0, 50));
250+
}
251+
252+
if ($this->resolveLinks && null !== $request->resolveLinks->type) {
253+
/**
254+
* There is a limit of possible resolvable relations.
255+
*
256+
* @see https://www.storyblok.com/docs/guide/in-depth/rendering-the-link-field
257+
*/
258+
$limit = match ($request->resolveLinks->type) {
259+
LinkType::Story => 50,
260+
LinkType::Link, LinkType::Url => 500,
261+
};
262+
263+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->links, 0, $limit));
264+
}
133265

134266
return new StoryResponse([
135267
'cv' => $response->cv,
136268
'rels' => $response->rels,
137269
'links' => $response->links,
138-
'story' => $story,
270+
'story' => $resolvedStory,
139271
]);
140272
}
141273

142274
public function byId(Id $id, ?StoryRequest $request = null): StoryResponse
143275
{
144276
$response = $this->storiesApi->byId($id, $request);
145277

146-
$story = $this->resolver->resolve($response->story, $response->rels);
278+
if (null === $request) {
279+
return $response;
280+
}
281+
282+
$resolvedStory = $response->story;
283+
284+
if ($this->resolveRelations && 0 !== $request->withRelations->count()) {
285+
/**
286+
* There is a limit of possible resolvable relations.
287+
*
288+
* @see https://www.storyblok.com/docs/api/content-delivery/v2/stories/retrieve-a-single-story
289+
*/
290+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->rels, 0, 50));
291+
}
292+
293+
if ($this->resolveLinks && null !== $request->resolveLinks->type) {
294+
/**
295+
* There is a limit of possible resolvable relations.
296+
*
297+
* @see https://www.storyblok.com/docs/guide/in-depth/rendering-the-link-field
298+
*/
299+
$limit = match ($request->resolveLinks->type) {
300+
LinkType::Story => 50,
301+
LinkType::Link, LinkType::Url => 500,
302+
};
303+
304+
$resolvedStory = $this->resolver->resolve($resolvedStory, \array_slice($response->links, 0, $limit));
305+
}
147306

148307
return new StoryResponse([
149308
'cv' => $response->cv,
150309
'rels' => $response->rels,
151310
'links' => $response->links,
152-
'story' => $story,
311+
'story' => $resolvedStory,
153312
]);
154313
}
155314
}

tests/Unit/Request/StoryRequestTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717
use PHPUnit\Framework\Attributes\Test;
1818
use PHPUnit\Framework\TestCase;
1919
use Storyblok\Api\Domain\Value\Dto\Version;
20+
use Storyblok\Api\Domain\Value\Resolver\LinkLevel;
21+
use Storyblok\Api\Domain\Value\Resolver\LinkType;
2022
use Storyblok\Api\Domain\Value\Resolver\Relation;
2123
use Storyblok\Api\Domain\Value\Resolver\RelationCollection;
24+
use Storyblok\Api\Domain\Value\Resolver\ResolveLinks;
2225
use Storyblok\Api\Request\StoryRequest;
2326
use Storyblok\Api\Tests\Util\FakerTrait;
2427

@@ -81,4 +84,18 @@ public function toArrayWithRelations(): void
8184
'resolve_relations' => 'root.relation,root.another_relation',
8285
], $request->toArray());
8386
}
87+
88+
#[Test]
89+
public function toArrayResolveLinks(): void
90+
{
91+
$request = new StoryRequest(
92+
resolveLinks: new ResolveLinks(LinkType::Story, LinkLevel::Deep),
93+
);
94+
95+
self::assertSame([
96+
'language' => 'default',
97+
'resolve_links' => 'story',
98+
'resolve_links_level' => 2,
99+
], $request->toArray());
100+
}
84101
}

0 commit comments

Comments
 (0)