Skip to content

Commit 9de3a49

Browse files
authored
ensure resource array promises automatically filter out nulls (#38)
1 parent e7df0e3 commit 9de3a49

File tree

5 files changed

+60
-5
lines changed

5 files changed

+60
-5
lines changed

src/Promise/ResolvedResourceTrait.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Markup\Contentful\Promise;
44

55
use function GuzzleHttp\Promise\is_fulfilled;
6+
use GuzzleHttp\Promise\PromiseInterface;
67
use Markup\Contentful\ResourceArray;
78
use Markup\Contentful\ResourceInterface;
89

@@ -21,7 +22,17 @@ private function ensureResolved()
2122
if (is_fulfilled($promise) && null !== $this->resolvedResource) {
2223
return;
2324
}
24-
$this->resolvedResource = $promise->wait();
25+
$this->doResolve($promise);
26+
}
27+
28+
protected function doResolve(PromiseInterface $promise)
29+
{
30+
$this->setResolvedResource($promise->wait());
31+
}
32+
33+
protected function setResolvedResource($resource)
34+
{
35+
$this->resolvedResource = $resource;
2536
}
2637

2738
/**

src/Promise/ResourceArrayPromise.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,19 @@ protected function addRejectionHandlerToPromise(PromiseInterface $promise)
145145
return new ResourceArray([], 0, 0, 0);
146146
});
147147
}
148+
149+
protected function doResolve(PromiseInterface $promise)
150+
{
151+
$resolved = $promise->wait();
152+
//temporarily set resolved resource with array that may contain nulls
153+
$this->setResolvedResource($resolved);
154+
//now set it again but with access to skip/limit parameters etc - using a resource array will auto-filter nulls
155+
$this->setResolvedResource(new ResourceArray(
156+
$resolved,
157+
$this->getTotal(),
158+
$this->getSkip(),
159+
$this->getLimit(),
160+
$this->getEnvelope()
161+
));
162+
}
148163
}

src/ResourceArray.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ public function __construct($items, $total, $skip, $limit, ResourceEnvelope $env
4545
return $resource instanceof ResourceInterface;
4646
};
4747
if ($items instanceof \Traversable) {
48-
$this->items = array_filter(array_values(iterator_to_array($items)), $filterNonResource);
48+
$this->items = array_values(array_filter(array_values(iterator_to_array($items)), $filterNonResource));
4949
} elseif (is_array($items)) {
50-
$this->items = array_filter(array_values($items), $filterNonResource);
50+
$this->items = array_values(array_filter(array_values($items), $filterNonResource));
5151
} else {
5252
throw new \InvalidArgumentException('Items parameter should be an array or a traversable object.');
5353
}
@@ -157,4 +157,17 @@ public function offsetGet($offset)
157157

158158
return $this->items[$offset];
159159
}
160+
161+
/**
162+
* Ensures that this resource array strips out missing resources if they don't exist, so that counts and members
163+
* always reflect resources only.
164+
*
165+
* This will resolve a resource array if it is a promise/ future.
166+
*
167+
* @return void
168+
*/
169+
public function ensureNoMissing()
170+
{
171+
// constructor already ensures no missing, so no action necessary here
172+
}
160173
}

tests/Promise/ResourceArrayPromiseTest.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ public function testIsPromise()
3737
public function testGetEnvelope()
3838
{
3939
$envelope = m::mock(ResourceEnvelope::class);
40-
$inner = m::mock(ResourceArrayInterface::class)
40+
$inner = m::spy(ResourceArrayInterface::class)
4141
->shouldReceive('getEnvelope')
4242
->andReturn($envelope)
43+
->shouldReceive('getIterator')
44+
->andReturn(new \ArrayIterator())
4345
->getMock();
4446
$resourceArray = new ResourceArrayPromise(promise_for($inner));
4547
$this->assertSame($envelope, $resourceArray->getEnvelope());
@@ -56,4 +58,17 @@ public function testGettersForArray()
5658
$this->assertInstanceOf(EntryInterface::class, $resourceArray->first());
5759
$this->assertInstanceOf(AssetInterface::class, $resourceArray->last());
5860
}
61+
62+
public function testFiltersEmpty()
63+
{
64+
$resourceArray = new ResourceArrayPromise(promise_for([
65+
m::mock(EntryInterface::class),
66+
null,
67+
m::mock(AssetInterface::class),
68+
]));
69+
$this->assertCount(2, $resourceArray);
70+
$this->assertInstanceOf(EntryInterface::class, $resourceArray->first());
71+
$this->assertInstanceOf(AssetInterface::class, $resourceArray->last());
72+
$this->assertInstanceOf(AssetInterface::class, $resourceArray[1]);
73+
}
5974
}

tests/ResourceArrayTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Markup\Contentful\Tests;
44

5+
use Markup\Contentful\EntryInterface;
56
use Markup\Contentful\ResourceArray;
67
use Markup\Contentful\ResourceArrayInterface;
78
use Mockery as m;
@@ -85,6 +86,6 @@ public function testLastWhenArrayEmptyReturnsNull()
8586

8687
private function getMockEntry()
8788
{
88-
return m::mock('Markup\Contentful\EntryInterface');
89+
return m::mock(EntryInterface::class);
8990
}
9091
}

0 commit comments

Comments
 (0)