Skip to content

Commit d39c321

Browse files
committed
Added SingleRecordResource interface that resources must implement to be used with Porter::importOne().
1 parent d5e5511 commit d39c321

File tree

6 files changed

+70
-1
lines changed

6 files changed

+70
-1
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace ScriptFUSION\Porter;
5+
6+
use ScriptFUSION\Porter\Provider\Resource\SingleRecordResource;
7+
8+
/**
9+
* The exception that is throw when a resource is incompatible with an importOne operation because it is not marked
10+
* with the single record interface.
11+
*/
12+
final class IncompatibleResourceException extends \LogicException
13+
{
14+
public function __construct()
15+
{
16+
parent::__construct('Cannot import one: resource does not implement ' . SingleRecordResource::class . '.');
17+
}
18+
}

src/Porter.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use ScriptFUSION\Porter\Provider\Provider;
2222
use ScriptFUSION\Porter\Provider\ProviderFactory;
2323
use ScriptFUSION\Porter\Provider\Resource\ProviderResource;
24+
use ScriptFUSION\Porter\Provider\Resource\SingleRecordResource;
2425
use ScriptFUSION\Porter\Specification\AsyncImportSpecification;
2526
use ScriptFUSION\Porter\Specification\ImportSpecification;
2627
use ScriptFUSION\Porter\Transform\AsyncTransformer;
@@ -86,6 +87,10 @@ public function import(ImportSpecification $specification): PorterRecords
8687
*/
8788
public function importOne(ImportSpecification $specification): ?array
8889
{
90+
if (!$specification->getResource() instanceof SingleRecordResource) {
91+
throw new IncompatibleResourceException;
92+
}
93+
8994
$results = $this->import($specification);
9095

9196
if (!$results->valid()) {
@@ -162,6 +167,10 @@ public function importAsync(AsyncImportSpecification $specification): AsyncRecor
162167
public function importOneAsync(AsyncImportSpecification $specification): Promise
163168
{
164169
return call(function () use ($specification) {
170+
if (!$specification->getAsyncResource() instanceof SingleRecordResource) {
171+
throw new IncompatibleResourceException;
172+
}
173+
165174
$results = $this->importAsync($specification);
166175

167176
yield $results->advance();
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace ScriptFUSION\Porter\Provider\Resource;
5+
6+
/**
7+
* Marker interface that specifies a resource that only fetches a single record and whose iterator is thus only valid
8+
* for one iteration. Such resources are intended to be used with Porter::importOne() rather than import().
9+
*/
10+
interface SingleRecordResource
11+
{
12+
// Marker interface.
13+
}

test/Integration/PorterAsyncTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
use ScriptFUSION\Porter\ForeignResourceException;
1313
use ScriptFUSION\Porter\ImportException;
1414
use ScriptFUSION\Porter\IncompatibleProviderException;
15+
use ScriptFUSION\Porter\IncompatibleResourceException;
1516
use ScriptFUSION\Porter\Porter;
1617
use ScriptFUSION\Porter\PorterAware;
1718
use ScriptFUSION\Porter\Provider\Provider;
19+
use ScriptFUSION\Porter\Provider\Resource\AsyncResource;
20+
use ScriptFUSION\Porter\Provider\Resource\SingleRecordResource;
1821
use ScriptFUSION\Porter\Specification\AsyncImportSpecification;
1922
use ScriptFUSION\Porter\Transform\AsyncTransformer;
2023
use ScriptFUSION\Porter\Transform\FilterTransformer;
@@ -51,6 +54,17 @@ public function testImportOneAsync(): \Generator
5154
self::assertSame(['foo'], yield $this->porter->importOneAsync($this->specification));
5255
}
5356

57+
/**
58+
* Tests that when importing one from a resource not marked with SingleRecordResource, an exception is thrown.
59+
*/
60+
public function testImportOneNonSingleAsync(): \Generator
61+
{
62+
$this->expectException(IncompatibleResourceException::class);
63+
$this->expectExceptionMessage(SingleRecordResource::class);
64+
65+
yield $this->porter->importOneAsync(new AsyncImportSpecification(\Mockery::mock(AsyncResource::class)));
66+
}
67+
5468
/**
5569
* Tests that when the resource is countable, the count is propagated to the outermost collection and the records
5670
* are intact.

test/Integration/PorterSyncTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
use ScriptFUSION\Porter\ForeignResourceException;
1717
use ScriptFUSION\Porter\ImportException;
1818
use ScriptFUSION\Porter\IncompatibleProviderException;
19+
use ScriptFUSION\Porter\IncompatibleResourceException;
1920
use ScriptFUSION\Porter\PorterAware;
2021
use ScriptFUSION\Porter\Provider\AsyncProvider;
22+
use ScriptFUSION\Porter\Provider\Resource\ProviderResource;
23+
use ScriptFUSION\Porter\Provider\Resource\SingleRecordResource;
2124
use ScriptFUSION\Porter\ProviderNotFoundException;
2225
use ScriptFUSION\Porter\Specification\ImportSpecification;
2326
use ScriptFUSION\Porter\Specification\StaticDataImportSpecification;
@@ -209,6 +212,17 @@ public function testImportOneOfMany(): void
209212
$this->porter->importOne($this->specification);
210213
}
211214

215+
/**
216+
* Tests that when importing one from a resource not marked with SingleRecordResource, an exception is thrown.
217+
*/
218+
public function testImportOneNonSingleAsync(): \Generator
219+
{
220+
$this->expectException(IncompatibleResourceException::class);
221+
$this->expectExceptionMessage(SingleRecordResource::class);
222+
223+
yield $this->porter->importOne(new ImportSpecification(\Mockery::mock(ProviderResource::class)));
224+
}
225+
212226
#endregion
213227

214228
#region Durability

test/MockFactory.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ScriptFUSION\Porter\Provider\Provider;
1717
use ScriptFUSION\Porter\Provider\Resource\AsyncResource;
1818
use ScriptFUSION\Porter\Provider\Resource\ProviderResource;
19+
use ScriptFUSION\Porter\Provider\Resource\SingleRecordResource;
1920
use ScriptFUSION\StaticClass;
2021

2122
final class MockFactory
@@ -54,7 +55,7 @@ public static function mockProvider()
5455
*/
5556
public static function mockResource(Provider $provider, \Iterator $return = null)
5657
{
57-
$resource = \Mockery::mock(ProviderResource::class, AsyncResource::class)
58+
$resource = \Mockery::mock(ProviderResource::class, AsyncResource::class, SingleRecordResource::class)
5859
->shouldReceive('getProviderClassName')
5960
->andReturn(\get_class($provider))
6061
->shouldReceive('fetch')

0 commit comments

Comments
 (0)