Skip to content

Commit be84508

Browse files
committed
Merge branch 'sync'
2 parents 5ebc736 + 2791847 commit be84508

File tree

5 files changed

+95
-21
lines changed

5 files changed

+95
-21
lines changed

src/Sync/Concept/SyncDefinition.php

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Lkrms\Support\Catalog\ArrayKeyConformity;
1010
use Lkrms\Support\Catalog\ArrayMapperFlag;
1111
use Lkrms\Support\Iterator\Contract\FluentIteratorInterface;
12+
use Lkrms\Support\Iterator\IterableIterator;
1213
use Lkrms\Support\Pipeline;
1314
use Lkrms\Sync\Catalog\SyncEntitySource;
1415
use Lkrms\Sync\Catalog\SyncFilterPolicy;
@@ -20,7 +21,6 @@
2021
use Lkrms\Sync\Contract\ISyncProvider;
2122
use Lkrms\Sync\Exception\SyncEntityNotFoundException;
2223
use Lkrms\Sync\Exception\SyncFilterPolicyViolationException;
23-
use Lkrms\Sync\Support\SyncIntrospectionClass;
2424
use Lkrms\Sync\Support\SyncIntrospector;
2525
use Closure;
2626
use LogicException;
@@ -58,16 +58,17 @@ abstract class SyncDefinition extends FluentInterface implements ISyncDefinition
5858
* {@see SyncDefinition::$Operations}.
5959
*
6060
* @param OP::* $operation
61+
* @return (Closure(ISyncContext, mixed...): (iterable<TEntity>|TEntity))|null
6162
* @phpstan-return (
6263
* $operation is OP::READ
6364
* ? (Closure(ISyncContext, int|string|null, mixed...): TEntity)
6465
* : (
6566
* $operation is OP::READ_LIST
66-
* ? (Closure(ISyncContext, mixed...): FluentIteratorInterface<array-key,TEntity>)
67+
* ? (Closure(ISyncContext, mixed...): iterable<TEntity>)
6768
* : (
6869
* $operation is OP::CREATE|OP::UPDATE|OP::DELETE
6970
* ? (Closure(ISyncContext, TEntity, mixed...): TEntity)
70-
* : (Closure(ISyncContext, FluentIteratorInterface<array-key,TEntity>, mixed...): FluentIteratorInterface<array-key,TEntity>)
71+
* : (Closure(ISyncContext, iterable<TEntity>, mixed...): iterable<TEntity>)
7172
* )
7273
* )
7374
* )|null
@@ -317,7 +318,10 @@ final public function getSyncOperationClosure($operation): ?Closure
317318
($closure = $this->getSyncOperationClosure(OP::READ_LIST))) {
318319
return $this->Closures[$operation] =
319320
function (ISyncContext $ctx, $id, ...$args) use ($closure) {
320-
$entity = $closure($ctx, ...$args)->nextWithValue('Id', $id);
321+
$entity =
322+
$this
323+
->getFluentIterator($closure($ctx, ...$args))
324+
->nextWithValue('Id', $id);
321325
if ($entity === false) {
322326
throw new SyncEntityNotFoundException($this->Provider, $this->Entity, $id);
323327
}
@@ -341,11 +345,27 @@ function (ISyncContext $ctx, $id, ...$args) use ($closure) {
341345
* Useful within overrides when a fallback implementation is required.
342346
*
343347
* @param OP::* $operation
348+
* @return (Closure(ISyncContext, mixed...): (iterable<TEntity>|TEntity))|null
349+
* @phpstan-return (
350+
* $operation is OP::READ
351+
* ? (Closure(ISyncContext, int|string|null, mixed...): TEntity)
352+
* : (
353+
* $operation is OP::READ_LIST
354+
* ? (Closure(ISyncContext, mixed...): iterable<TEntity>)
355+
* : (
356+
* $operation is OP::CREATE|OP::UPDATE|OP::DELETE
357+
* ? (Closure(ISyncContext, TEntity, mixed...): TEntity)
358+
* : (Closure(ISyncContext, iterable<TEntity>, mixed...): iterable<TEntity>)
359+
* )
360+
* )
361+
* )|null
362+
*
344363
* @see SyncDefinition::$Overrides
345364
*/
346-
final public function getFallbackSyncOperationClosure($operation): ?Closure
365+
final public function getFallbackClosure($operation): ?Closure
347366
{
348-
if (!($clone = $this->WithoutOverrides)) {
367+
$clone = $this->WithoutOverrides;
368+
if (!$clone) {
349369
$clone = clone $this;
350370
$clone->Overrides = [];
351371
$this->WithoutOverrides = $clone;
@@ -354,6 +374,44 @@ final public function getFallbackSyncOperationClosure($operation): ?Closure
354374
return $clone->getSyncOperationClosure($operation);
355375
}
356376

377+
/**
378+
* @deprecated Use {@see SyncDefinition::getFallbackClosure()} instead
379+
*
380+
* @param OP::* $operation
381+
* @return (Closure(ISyncContext, mixed...): (iterable<TEntity>|TEntity))|null
382+
* @phpstan-return (
383+
* $operation is OP::READ
384+
* ? (Closure(ISyncContext, int|string|null, mixed...): TEntity)
385+
* : (
386+
* $operation is OP::READ_LIST
387+
* ? (Closure(ISyncContext, mixed...): iterable<TEntity>)
388+
* : (
389+
* $operation is OP::CREATE|OP::UPDATE|OP::DELETE
390+
* ? (Closure(ISyncContext, TEntity, mixed...): TEntity)
391+
* : (Closure(ISyncContext, iterable<TEntity>, mixed...): iterable<TEntity>)
392+
* )
393+
* )
394+
* )|null
395+
*/
396+
final public function getFallbackSyncOperationClosure($operation): ?Closure
397+
{
398+
return $this->getFallbackClosure($operation);
399+
}
400+
401+
/**
402+
* Specify whether to perform READ operations by iterating over entities
403+
* returned by READ_LIST
404+
*
405+
* @return $this
406+
*/
407+
final public function withReadFromReadList(bool $readFromReadList = true)
408+
{
409+
$clone = clone $this;
410+
$clone->ReadFromReadList = $readFromReadList;
411+
412+
return $clone;
413+
}
414+
357415
/**
358416
* Get an entity-to-data pipeline for the entity
359417
*
@@ -476,6 +534,19 @@ function (ISyncContext $ctx, ?bool &$returnEmpty, &$empty) use ($operation): voi
476534
);
477535
}
478536

537+
/**
538+
* @param iterable<TEntity> $result
539+
* @return FluentIteratorInterface<array-key,TEntity>
540+
*/
541+
private function getFluentIterator(iterable $result): FluentIteratorInterface
542+
{
543+
if (!($result instanceof FluentIteratorInterface)) {
544+
return new IterableIterator($result);
545+
}
546+
547+
return $result;
548+
}
549+
479550
public static function getReadable(): array
480551
{
481552
return [

src/Sync/Contract/ISyncDefinition.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Lkrms\Sync\Contract;
44

55
use Lkrms\Contract\IImmutable;
6-
use Lkrms\Support\Iterator\Contract\FluentIteratorInterface;
76
use Lkrms\Sync\Catalog\SyncOperation;
87
use Closure;
98

@@ -21,17 +20,17 @@ interface ISyncDefinition extends IImmutable
2120
* entity
2221
*
2322
* @param SyncOperation::* $operation
24-
* @return (Closure(ISyncContext, mixed...): FluentIteratorInterface<array-key,TEntity>|TEntity)|null `null` if `$operation` is not supported, otherwise a closure with the correct signature for the sync operation.
23+
* @return (Closure(ISyncContext, mixed...): (iterable<TEntity>|TEntity))|null `null` if `$operation` is not supported, otherwise a closure with the correct signature for the sync operation.
2524
* @phpstan-return (
2625
* $operation is SyncOperation::READ
2726
* ? (Closure(ISyncContext, int|string|null, mixed...): TEntity)
2827
* : (
2928
* $operation is SyncOperation::READ_LIST
30-
* ? (Closure(ISyncContext, mixed...): FluentIteratorInterface<array-key,TEntity>)
29+
* ? (Closure(ISyncContext, mixed...): iterable<TEntity>)
3130
* : (
3231
* $operation is SyncOperation::CREATE|SyncOperation::UPDATE|SyncOperation::DELETE
3332
* ? (Closure(ISyncContext, TEntity, mixed...): TEntity)
34-
* : (Closure(ISyncContext, FluentIteratorInterface<array-key,TEntity>, mixed...): FluentIteratorInterface<array-key,TEntity>)
33+
* : (Closure(ISyncContext, iterable<TEntity>, mixed...): iterable<TEntity>)
3534
* )
3635
* )
3736
* )|null

src/Sync/Support/SyncContext.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,16 @@ private function doGetFilter(string $key, bool $claim = false)
209209
return null;
210210
}
211211
$name = Convert::toSnakeCase(substr($key, 0, -3));
212-
$key = $this->FilterKeys[$name] ?? null;
213-
if ($key === null) {
212+
if (array_key_exists($name, $this->FilterKeys)) {
213+
$key = $this->FilterKeys[$name];
214+
if ($claim) {
215+
unset($this->FilterKeys[$name]);
216+
}
217+
} elseif (array_key_exists($name, $this->Filters)) {
218+
$key = $name;
219+
} else {
214220
return null;
215221
}
216-
if ($claim) {
217-
unset($this->FilterKeys[$name]);
218-
}
219222
}
220223
}
221224

src/Sync/Support/SyncEntityProvider.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ public function __construct(
103103
/**
104104
* @param SyncOperation::* $operation
105105
* @param mixed ...$args
106-
* @return FluentIteratorInterface<array-key,TEntity>|TEntity
106+
* @return iterable<TEntity>|TEntity
107107
* @phpstan-return (
108108
* $operation is SyncOperation::*_LIST
109-
* ? FluentIteratorInterface<array-key,TEntity>
109+
* ? iterable<TEntity>
110110
* : TEntity
111111
* )
112112
*/
@@ -460,9 +460,10 @@ public function runA($operation, ...$args): array
460460

461461
$fromCheckpoint = $this->Store->getDeferredEntityCheckpoint();
462462

463-
$result = iterator_to_array(
464-
$this->_run($operation, ...$args)
465-
);
463+
$result = $this->_run($operation, ...$args);
464+
if (!is_array($result)) {
465+
$result = iterator_to_array($result);
466+
}
466467

467468
if ($this->Context->getDeferredSyncEntityPolicy() !==
468469
DeferredEntityPolicy::DO_NOT_RESOLVE) {

src/Sync/Support/SyncIntrospector.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,8 @@ static function (
267267
*
268268
* @param SyncOperation::* $operation
269269
* @param class-string<T>|static<T> $entity
270+
* @return (Closure(ISyncContext, mixed...): (iterable<T>|T))|null
270271
*
271-
* @return (Closure(ISyncContext, mixed...): mixed)|null
272272
* @throws LogicException if the {@see SyncIntrospector} and `$entity` don't
273273
* respectively represent an {@see ISyncProvider} and {@see ISyncEntity}.
274274
*/

0 commit comments

Comments
 (0)