Skip to content

Commit 74f647c

Browse files
Douglas Greenshieldsshieldo
authored andcommitted
ensure entries and assets are resolved with contextual locale
1 parent ed2814e commit 74f647c

File tree

7 files changed

+130
-65
lines changed

7 files changed

+130
-65
lines changed

phpunit.xml.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<phpunit bootstrap="./vendor/autoload.php" colors="true">
44

55
<testsuites>
6-
<testsuite name="contentful api client test suite">
6+
<testsuite name="Contentful API client test suite">
77
<directory suffix="Test.php">./tests</directory>
88
</testsuite>
99
</testsuites>

src/Contentful.php

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Markup\Contentful\Exception\ResourceUnavailableException;
1616
use Markup\Contentful\Filter\ContentTypeFilterProvider;
1717
use Markup\Contentful\Filter\DecidesCacheKeyInterface;
18+
use Markup\Contentful\Filter\LocaleFilter;
1819
use Markup\Contentful\Log\LoggerInterface;
1920
use Markup\Contentful\Log\LogInterface;
2021
use Markup\Contentful\Log\NullLogger;
@@ -147,15 +148,16 @@ public function getSpaceAsync($space = null, array $options = [])
147148
* @param string $id
148149
* @param string|SpaceInterface $space
149150
* @param array $options A set of options for the fetch, including 'include_level' being how many levels to include
151+
* @param string $locale A locale for the entry data, if one is specified (otherwise, API will use default locale for the space)
150152
* @return EntryInterface|PromiseInterface
151153
* @throws Exception\ResourceUnavailableException
152154
*/
153-
public function getEntry($id, $space = null, array $options = [])
155+
public function getEntry($id, $space = null, array $options = [], $locale = null)
154156
{
155-
if ($this->envelope->hasEntry($id)) {
157+
if ($this->envelope->hasEntry($id, $locale)) {
156158
return ($this->isAsyncCall($options))
157-
? promise_for($this->envelope->findEntry($id))
158-
: $this->envelope->findEntry($id);
159+
? promise_for($this->envelope->findEntry($id, $locale))
160+
: $this->envelope->findEntry($id, $locale);
159161
}
160162
$spaceName = ($space instanceof SpaceInterface) ? $space->getName() : $space;
161163
$spaceData = $this->getSpaceDataForName(($space instanceof SpaceInterface) ? $space->getName() : $space);
@@ -169,7 +171,7 @@ public function getEntry($id, $space = null, array $options = [])
169171
$api,
170172
'entry',
171173
strval($id),
172-
[],
174+
($locale) ? [new LocaleFilter($locale)] : [],
173175
$options
174176
);
175177
}
@@ -178,12 +180,13 @@ public function getEntry($id, $space = null, array $options = [])
178180
* @param string $id
179181
* @param string|SpaceInterface $space
180182
* @param array $options
183+
* @param string|null $locale
181184
* @return EntryInterface|PromiseInterface
182185
*/
183-
public function getEntryAsync($id, $space = null, array $options = [])
186+
public function getEntryAsync($id, $space = null, array $options = [], $locale = null)
184187
{
185188
return new EntryPromise(
186-
$this->getEntry($id, $space, array_merge($options, ['async' => true]))
189+
$this->getEntry($id, $space, array_merge($options, ['async' => true]), $locale)
187190
);
188191
}
189192

@@ -230,14 +233,15 @@ public function getEntriesAsync(array $parameters = [], $space = null, array $op
230233
* @param string $id
231234
* @param string|SpaceInterface $space
232235
* @param array $options
236+
* @param string|null $locale
233237
* @return AssetInterface|PromiseInterface
234238
*/
235-
public function getAsset($id, $space = null, array $options = [])
239+
public function getAsset($id, $space = null, array $options = [], $locale = null)
236240
{
237-
if ($this->envelope->hasAsset($id)) {
241+
if ($this->envelope->hasAsset($id, $locale)) {
238242
return ($this->isAsyncCall($options))
239-
? promise_for($this->envelope->findAsset($id))
240-
: $this->envelope->findAsset($id);
243+
? promise_for($this->envelope->findAsset($id, $locale))
244+
: $this->envelope->findAsset($id, $locale);
241245
}
242246
$spaceName = ($space instanceof SpaceInterface) ? $space->getName() : $space;
243247
$spaceData = $this->getSpaceDataForName($spaceName);
@@ -251,7 +255,7 @@ public function getAsset($id, $space = null, array $options = [])
251255
$api,
252256
'asset',
253257
strval($id),
254-
[],
258+
($locale) ? [new LocaleFilter($locale)] : [],
255259
$options
256260
);
257261
}
@@ -260,12 +264,13 @@ public function getAsset($id, $space = null, array $options = [])
260264
* @param string $id
261265
* @param string|SpaceInterface $space
262266
* @param array $options
267+
* @param string|null $locale
263268
* @return AssetInterface|PromiseInterface
264269
*/
265-
public function getAssetAsync($id, $space = null, array $options = [])
270+
public function getAssetAsync($id, $space = null, array $options = [], $locale = null)
266271
{
267272
return new AssetPromise(
268-
$this->getAsset($id, $space, array_merge($options, ['async' => true]))
273+
$this->getAsset($id, $space, array_merge($options, ['async' => true]), $locale)
269274
);
270275
}
271276

@@ -406,11 +411,12 @@ public function getContentTypeByNameAsync($name, $space = null, array $options =
406411
}
407412

408413
/**
409-
* @param Link $link
410-
* @param array $options
414+
* @param Link $link
415+
* @param array $options
416+
* @param string|null $locale
411417
* @return PromiseInterface
412418
*/
413-
public function resolveLink($link, array $options = [])
419+
public function resolveLink($link, array $options = [], $locale = null)
414420
{
415421
//check whether the "link" is already actually a resolved resource
416422
if ($link instanceof ResourceInterface) {
@@ -422,13 +428,15 @@ public function resolveLink($link, array $options = [])
422428
return $this->getEntry(
423429
$link->getId(),
424430
$link->getSpaceName(),
425-
array_merge($options, ['async' => true])
431+
array_merge($options, ['async' => true]),
432+
$locale
426433
);
427434
case 'Asset':
428435
return $this->getAsset(
429436
$link->getId(),
430437
$link->getSpaceName(),
431-
array_merge($options, ['async' => true])
438+
array_merge($options, ['async' => true]),
439+
$locale
432440
);
433441
case 'ContentType':
434442
return $this->getContentType(
@@ -876,8 +884,8 @@ private function buildResponseFromRaw(
876884
static $resourceBuilder;
877885
if (empty($resourceBuilder)) {
878886
$resourceBuilder = new ResourceBuilder($this->envelope);
879-
$resourceBuilder->setResolveLinkFunction(function ($link) {
880-
return $this->resolveLink($link);
887+
$resourceBuilder->setResolveLinkFunction(function ($link, $locale = null) {
888+
return $this->resolveLink($link, [], $locale);
881889
});
882890
}
883891
$resourceBuilder->setUseDynamicEntries($useTypedResources);

src/Entry.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function getField($key)
6262
if ($this->fields[$key] instanceof Link) {
6363
if (!isset($this->resolvedLinks[$key])) {
6464
try {
65-
$resolvedLink = call_user_func($this->resolveLinkFunction, $this->fields[$key])->wait();
65+
$resolvedLink = call_user_func($this->resolveLinkFunction, $this->fields[$key], $this->getLocale())->wait();
6666
} catch (LinkUnresolvableException $e) {
6767
$resolvedLink = null;
6868
} catch (ResourceUnavailableException $e) {
@@ -77,7 +77,7 @@ public function getField($key)
7777
if (!isset($this->resolvedLinks[$key])) {
7878
$this->resolvedLinks[$key] = array_filter(array_map(function ($link) {
7979
try {
80-
$resolvedLink = call_user_func($this->resolveLinkFunction, $link)->wait();
80+
$resolvedLink = call_user_func($this->resolveLinkFunction, $link, $this->getLocale())->wait();
8181
} catch (LinkUnresolvableException $e) {
8282
//if the link is unresolvable we should consider it not published and return null so this is filtered out
8383
return null;

src/ResourceBuilder.php

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,21 @@ public function __construct(ResourceEnvelope $envelope = null)
3838
* @param array $data The raw data returned from the Contentful APIs.
3939
* @param string $spaceName The name being used for the space this data is from.
4040
* @param AssetDecoratorInterface $assetDecorator
41+
* @param string|null $locale
4142
* @return PromiseInterface
4243
*/
43-
public function buildFromData(array $data, $spaceName = null, AssetDecoratorInterface $assetDecorator = null)
44-
{
44+
public function buildFromData(
45+
array $data,
46+
$spaceName = null,
47+
AssetDecoratorInterface $assetDecorator = null,
48+
$locale = null
49+
) {
4550
return coroutine(
46-
function () use ($data, $spaceName, $assetDecorator) {
51+
function () use ($data, $spaceName, $assetDecorator, $locale) {
4752
$assetDecorator = $assetDecorator ?: new NullAssetDecorator();
48-
$buildFromData = function ($data) use ($spaceName, $assetDecorator) {
49-
return $this->buildFromData($data, $spaceName, $assetDecorator);
53+
$dataLocale = $locale ?: ((isset($data['sys']['locale'])) ? $data['sys']['locale'] : null);
54+
$buildFromData = function ($data) use ($spaceName, $assetDecorator, $dataLocale) {
55+
return $this->buildFromData($data, $spaceName, $assetDecorator, $dataLocale);
5056
};
5157
if ($this->isArrayResourceData($data)) {
5258
yield all(
@@ -158,14 +164,14 @@ function () use ($data, $spaceName, $assetDecorator) {
158164
case 'Link':
159165
switch ($metadata->getLinkType()) {
160166
case 'Entry':
161-
$entry = $this->envelope->findEntry($metadata->getId());
167+
$entry = $this->envelope->findEntry($metadata->getId(), $dataLocale);
162168
if ($entry) {
163169
yield promise_for($entry);
164170
return;
165171
}
166172
break;
167173
case 'Asset':
168-
$asset = $this->envelope->findAsset($metadata->getId());
174+
$asset = $this->envelope->findAsset($metadata->getId(), $dataLocale);
169175
if ($asset) {
170176
yield promise_for($asset);
171177
return;
@@ -290,12 +296,13 @@ private function resolveResourceDataToEnvelopeResource(array $data)
290296
if (!isset($data['sys']['id']) || !isset($data['sys']['type'])) {
291297
return null;
292298
}
299+
$dataLocale = (isset($data['sys']['locale'])) ? $data['sys']['locale'] : null;
293300
switch ($data['sys']['type']) {
294301
case 'Entry':
295-
return $this->envelope->findEntry($data['sys']['id']);
302+
return $this->envelope->findEntry($data['sys']['id'], $dataLocale);
296303
break;
297304
case 'Asset':
298-
return $this->envelope->findAsset($data['sys']['id']);
305+
return $this->envelope->findAsset($data['sys']['id'], $dataLocale);
299306
break;
300307
case 'ContentType':
301308
return $this->envelope->findContentType($data['sys']['id']);
@@ -347,15 +354,17 @@ private function addToEnvelope(array $includesData, callable $buildFromData)
347354
function () use ($includesData, $buildFromData) {
348355
if (isset($includesData['Entry'])) {
349356
foreach ($includesData['Entry'] as $entryData) {
350-
if (!isset($entryData['sys']['id']) || $this->envelope->hasEntry($entryData['sys']['id'])) {
357+
$entryLocale = (isset($entryData['sys']['locale'])) ? $entryData['sys']['locale'] : null;
358+
if (!isset($entryData['sys']['id']) || $this->envelope->hasEntry($entryData['sys']['id'], $entryLocale)) {
351359
continue;
352360
}
353361
$this->envelope->insertEntry((yield $buildFromData($entryData)));
354362
}
355363
}
356364
if (isset($includesData['Asset'])) {
357365
foreach ($includesData['Asset'] as $assetData) {
358-
if (!isset($assetData['sys']['id']) || $this->envelope->hasAsset($assetData['sys']['id'])) {
366+
$assetLocale = (isset($assetData['sys']['locale'])) ? $assetData['sys']['locale'] : null;
367+
if (!isset($assetData['sys']['id']) || $this->envelope->hasAsset($assetData['sys']['id'], $assetLocale)) {
359368
continue;
360369
}
361370
$this->envelope->insertAsset((yield $buildFromData($assetData)));

src/ResourceEnvelope.php

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
*/
88
class ResourceEnvelope
99
{
10+
const WILDCARD_KEY = '*';
11+
1012
/**
11-
* A list of entries keyed by ID.
13+
* A list of entries keyed by locale, and then by ID.
1214
*
1315
* @var EntryInterface[]
1416
*/
@@ -43,46 +45,56 @@ public function __construct()
4345

4446
/**
4547
* @param string $entryId
48+
* @param string|null $locale
4649
* @return EntryInterface|null
4750
*/
48-
public function findEntry($entryId)
51+
public function findEntry($entryId, $locale = null)
4952
{
50-
if (!isset($this->entries[$entryId])) {
53+
$identifier = $this->getIdentifierForLocale($locale);
54+
if (!isset($this->entries[$identifier][$entryId])) {
5155
return null;
5256
}
5357

54-
return $this->entries[$entryId];
58+
return $this->entries[$identifier][$entryId];
5559
}
5660

5761
/**
5862
* @param string $entryId
63+
* @param string|null $locale
5964
* @return bool
6065
*/
61-
public function hasEntry($entryId)
66+
public function hasEntry($entryId, $locale = null)
6267
{
63-
return isset($this->entries[$entryId]);
68+
$identifier = $this->getIdentifierForLocale($locale);
69+
70+
return isset($this->entries[$identifier][$entryId]);
6471
}
6572

6673
/**
6774
* @param string $assetId
75+
* @param string|null $locale
6876
* @return AssetInterface|null
6977
*/
70-
public function findAsset($assetId)
78+
public function findAsset($assetId, $locale = null)
7179
{
72-
if (!isset($this->assets[$assetId])) {
80+
$identifier = $this->getIdentifierForLocale($locale);
81+
if (!isset($this->assets[$identifier][$assetId])) {
7382
return null;
7483
}
7584

76-
return $this->assets[$assetId];
85+
return $this->assets[$identifier][$assetId];
7786
}
7887

7988
/**
8089
* @param string $assetId
90+
* @param string|null $locale
8191
* @return bool
8292
*/
83-
public function hasAsset($assetId)
93+
public function hasAsset($assetId, $locale = null)
8494
{
85-
return isset($this->assets[$assetId]);
95+
$identifier = $this->getIdentifierForLocale($locale);
96+
97+
return isset($this->assets[$identifier][$assetId]);
8698
}
8799

88100
/**
@@ -152,7 +164,12 @@ public function insert($resource)
152164
*/
153165
public function insertEntry(EntryInterface $entry)
154166
{
155-
$this->entries[$entry->getId()] = $entry;
167+
if (!isset($this->entries[self::WILDCARD_KEY][$entry->getId()])) {
168+
$this->entries[self::WILDCARD_KEY][$entry->getId()] = $entry;
169+
}
170+
if (null !== $entry->getLocale()) {
171+
$this->entries[$entry->getLocale()][$entry->getId()] = $entry;
172+
}
156173

157174
return $this;
158175
}
@@ -163,7 +180,12 @@ public function insertEntry(EntryInterface $entry)
163180
*/
164181
public function insertAsset(AssetInterface $asset)
165182
{
166-
$this->assets[$asset->getId()] = $asset;
183+
if (!isset($this->assets[self::WILDCARD_KEY][$asset->getId()])) {
184+
$this->assets[self::WILDCARD_KEY][$asset->getId()] = $asset;
185+
}
186+
if (null !== $asset->getLocale()) {
187+
$this->assets[$asset->getLocale()][$asset->getId()] = $asset;
188+
}
167189

168190
return $this;
169191
}
@@ -213,15 +235,23 @@ public function getAllContentTypesForSpace($space)
213235
*/
214236
public function getEntryCount()
215237
{
216-
return count($this->entries);
238+
if (!isset($this->entries[self::WILDCARD_KEY])) {
239+
return 0;
240+
}
241+
242+
return count($this->entries[self::WILDCARD_KEY]);
217243
}
218244

219245
/**
220246
* @return int
221247
*/
222248
public function getAssetCount()
223249
{
224-
return count($this->assets);
250+
if (!isset($this->assets[self::WILDCARD_KEY])) {
251+
return 0;
252+
}
253+
254+
return count($this->assets[self::WILDCARD_KEY]);
225255
}
226256

227257
/**
@@ -231,4 +261,13 @@ public function getContentTypeCount()
231261
{
232262
return count($this->contentTypes);
233263
}
264+
265+
/**
266+
* @param string|null $locale
267+
* @return string
268+
*/
269+
private function getIdentifierForLocale($locale)
270+
{
271+
return $locale ?: self::WILDCARD_KEY;
272+
}
234273
}

0 commit comments

Comments
 (0)