Skip to content

Commit 83cb996

Browse files
authored
Merge pull request #271 from RonasIT/add-lazy-each
feat: add lazyEach to EntityControlTrait
2 parents 407fcfb + e3b757e commit 83cb996

5 files changed

Lines changed: 110 additions & 5 deletions

File tree

src/Traits/EntityControlTrait.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,16 @@ public function chunk(int $limit, Closure $callback, array $where = []): void
370370
$this->postQueryHook();
371371
}
372372

373+
public function lazyEach(Closure $callback, array $where = [], int $chunkSize = 500): void
374+
{
375+
$this
376+
->getQuery($where)
377+
->lazyById($chunkSize)
378+
->each($callback);
379+
380+
$this->postQueryHook();
381+
}
382+
373383
/**
374384
* Delete rows by list of values a particular field or primary key
375385
*

tests/EntityControlTraitTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,51 @@ public function testChunkEmptyResult()
920920
$this->assertSettablePropertiesReset(self::$testRepositoryClass);
921921
}
922922

923+
public function testLazyEach()
924+
{
925+
$mockResult = $this->getJsonFixture('lazy_each_query_result');
926+
927+
$this->mockLazyEach($mockResult);
928+
929+
$counter = 0;
930+
931+
self::$testRepositoryClass
932+
->withTrashed()
933+
->onlyTrashed()
934+
->force()
935+
->with('relation')
936+
->withCount('relation')
937+
->lazyEach(function () use (&$counter) {
938+
$counter++;
939+
}, chunkSize: 1);
940+
941+
$this->assertEquals(2, $counter);
942+
943+
$this->assertSettablePropertiesReset(self::$testRepositoryClass);
944+
}
945+
946+
public function testLazyEachEmptyResult()
947+
{
948+
$nullCondition = $this->lazyByIdInitialNullCondition();
949+
950+
$this->mockSelect(
951+
'select * from "test_models"'
952+
. ($nullCondition ? ' where "id" is not null' : '')
953+
. ' order by "id" asc limit 500',
954+
);
955+
956+
$counter = 0;
957+
958+
// TODO: remove withTrashed() after increase min Laravel version up to 13
959+
self::$testRepositoryClass
960+
->withTrashed()
961+
->lazyEach(function () use (&$counter) {
962+
$counter++;
963+
});
964+
965+
$this->assertEquals(0, $counter);
966+
}
967+
923968
public function testForceDeleteByList()
924969
{
925970
$this->mockDelete(

tests/MockTraitTest.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace RonasIT\Support\Tests;
44

55
use PHPUnit\Framework\ExpectationFailedException;
6+
use PHPUnit\Runner\Version as PhpUnitVersion;
67
use ReflectionClass;
78
use ReflectionProperty;
89
use RonasIT\Support\Tests\Support\Mock\TestMockClass;
@@ -219,12 +220,18 @@ protected function clearMockAssertionFailures(): void
219220
$class = $class->getParentClass();
220221
}
221222

222-
foreach ($class->getProperty('mockObjects')->getValue($this) as $entry) {
223-
$handler = $entry['mockObject']->__phpunit_getInvocationHandler();
224-
225-
$assertionFailureProp = new ReflectionProperty($handler, 'assertionFailure');
223+
// TODO: Remove after increase min PHPUnit version up to 11
224+
$isNewPhpunit = version_compare(PhpUnitVersion::id(), '11.0.0', '>=');
226225

227-
$assertionFailureProp->setValue($handler, null);
226+
foreach ($class->getProperty('mockObjects')->getValue($this) as $entry) {
227+
if ($isNewPhpunit) {
228+
$handler = $entry['mockObject']->__phpunit_getInvocationHandler();
229+
(new ReflectionProperty($handler, 'matchers'))->setValue($handler, []);
230+
(new ReflectionProperty($handler, 'assertionFailure'))->setValue($handler, null);
231+
} else {
232+
$handler = $entry->__phpunit_getInvocationHandler();
233+
(new ReflectionProperty($handler, 'matchers'))->setValue($handler, []);
234+
}
228235
}
229236
}
230237
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
{
3+
"id": 1,
4+
"name": "John",
5+
"email": "john@example.com",
6+
"created_at": "2020-01-01 00:00:00",
7+
"updated_at": "2020-01-01 00:00:00"
8+
},
9+
{
10+
"id": 2,
11+
"name": "Jane",
12+
"email": "jane@example.com",
13+
"created_at": "2020-01-01 00:00:00",
14+
"updated_at": "2020-01-01 00:00:00"
15+
}
16+
]

tests/support/Traits/SqlMockTrait.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,33 @@ protected function mockChunk(array $selectResult): void
142142
);
143143
}
144144

145+
// TODO: remove after increase min Laravel version up to 13
146+
protected function lazyByIdInitialNullCondition(): string
147+
{
148+
return version_compare(app()->version(), '12.4.0', '>=') ? ' and "id" is not null' : '';
149+
}
150+
151+
protected function mockLazyEach(array $selectResult): void
152+
{
153+
$mainQuery = 'select "test_models".*, (select count(*) from "relation_models" '
154+
. 'where "test_models"."id" = "relation_models"."test_model_id") as "relation_count" '
155+
. 'from "test_models" where "test_models"."deleted_at" is not null';
156+
157+
$firstRow = array_shift($selectResult);
158+
$lastId = $firstRow['id'];
159+
160+
$this->mockSelect("{$mainQuery}{$this->lazyByIdInitialNullCondition()} order by \"id\" asc limit 1", [$firstRow]);
161+
$this->mockSelect("select * from \"relation_models\" where \"relation_models\".\"test_model_id\" in ({$lastId})");
162+
163+
foreach ($selectResult as $row) {
164+
$this->mockSelect("{$mainQuery} and \"id\" > ? order by \"id\" asc limit 1", [$row], [$lastId]);
165+
$this->mockSelect("select * from \"relation_models\" where \"relation_models\".\"test_model_id\" in ({$row['id']})");
166+
$lastId = $row['id'];
167+
}
168+
169+
$this->mockSelect("{$mainQuery} and \"id\" > ? order by \"id\" asc limit 1", [], [$lastId]);
170+
}
171+
145172
protected function mockCreate(array $selectResult, $notFillableValue): void
146173
{
147174
$this->mockInsert(

0 commit comments

Comments
 (0)