Skip to content

Commit 26be5d7

Browse files
committed
Bugfix nested reindex overwrite
1 parent 5f8ad90 commit 26be5d7

2 files changed

Lines changed: 91 additions & 11 deletions

File tree

src/Model.php

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ class Model extends \CodeIgniter\Model
1717
// Array of tables to block from loading relations
1818
protected $without = [];
1919

20+
// Whether to reindex results by the primary key
21+
protected $reindex = true;
22+
2023
// Call the CI model constructor then check for and load the schema
2124
public function __construct(ConnectionInterface &$db = null, ValidationInterface $validation = null)
2225
{
@@ -90,7 +93,48 @@ public function without($tables)
9093

9194
return $this;
9295
}
96+
97+
/**
98+
* Reset per-query variables.
99+
*
100+
* @return $this
101+
*/
102+
public function resetTmp()
103+
{
104+
unset($this->tmpWith, $this->tmpWithout, $this->tmpReindex);
105+
106+
return $this;
107+
}
93108

109+
/**
110+
* Enable/disable result reindexing.
111+
*
112+
* @param bool $bool
113+
*
114+
* @return $this
115+
*/
116+
public function reindex(bool $bool = true)
117+
{
118+
$this->reindex = $bool;
119+
120+
return $this;
121+
}
122+
123+
/**
124+
* Intercept join requests to disable reindexing.
125+
*
126+
* @return $this
127+
*/
128+
public function join(...$params)
129+
{
130+
$this->tmpReindex = false;
131+
132+
// Pass through to the builder
133+
$this->builder()->join(...$params);
134+
135+
return $this;
136+
}
137+
94138
//--------------------------------------------------------------------
95139
// FINDERS EXTENSIONS
96140
//--------------------------------------------------------------------
@@ -165,14 +209,14 @@ protected function addRelated($rows): ?array
165209
// If there were no matches then reset per-query data and quit
166210
if (empty($rows))
167211
{
168-
unset($this->tmpWith, $this->tmpWithout);
212+
$this->tmpReset();
169213
return $rows;
170214
}
171215

172216
// Likewise for empty singletons
173217
if (count($rows) == 1 && reset($rows) == null)
174218
{
175-
unset($this->tmpWith, $this->tmpWithout);
219+
$this->tmpReset();
176220
return $rows;
177221
}
178222

@@ -186,15 +230,21 @@ protected function addRelated($rows): ?array
186230
{
187231
$this->tmpWithout = $this->without;
188232
}
233+
// If no tmpReindex was set then use this model's default
234+
if (! isset($this->tmpReindex))
235+
{
236+
$this->tmpReindex = $this->reindex;
237+
}
189238

190239
// Remove any blocked tables from the request
191240
$this->tmpWith = array_diff($this->tmpWith, $this->tmpWithout);
192241

193242
// If tmpWith ends up empty then reset and quit
194243
if (empty($this->tmpWith))
195244
{
196-
unset($this->tmpWith, $this->tmpWithout);
197-
return $this->simpleReindex($rows);
245+
$rows = $this->tmpReindex ? $this->simpleReindex($rows) : $rows;
246+
$this->tmpReset();
247+
return $rows;
198248
}
199249

200250
// Make sure the schema is loaded
@@ -210,7 +260,7 @@ protected function addRelated($rows): ?array
210260
$relations[$tableName] = $this->findRelated($tableName, $ids);
211261
}
212262

213-
// Reindex $rows by this model's primary key and inject related items
263+
// Inject related items
214264
$return = [];
215265
foreach ($rows as $item)
216266
{
@@ -257,11 +307,19 @@ protected function addRelated($rows): ?array
257307
}
258308
}
259309

260-
$return[$id] = $item;
310+
if ($this->tmpReindex)
311+
{
312+
$return[$id] = $item;
313+
}
314+
else
315+
{
316+
$return[] = $item;
317+
}
261318
}
262319

263320
// Clear old data and reset per-query properties
264-
unset($rows, $this->tmpWith, $this->tmpWithout);
321+
unset($rows);
322+
$this->resetTmp();
265323

266324
return $return;
267325
}
@@ -310,6 +368,9 @@ public function findRelated($tableName, $ids): array
310368
// Check for another Relations model to prevent nesting loops
311369
if ($builder instanceof self)
312370
{
371+
// Don't reindex (we'll do our own below)
372+
$builder->reindex(false);
373+
313374
// If nesting is allowed we need to disable the target table
314375
if (self::$config->allowNesting)
315376
{
@@ -389,7 +450,7 @@ public function findRelated($tableName, $ids): array
389450

390451
// Clean up
391452
unset($table, $relation, $builder);
392-
453+
393454
// Reindex the results by the originating ID (this model's primary key)
394455
$return = [];
395456
if ($returnType == 'array')
@@ -416,15 +477,15 @@ public function findRelated($tableName, $ids): array
416477
}
417478

418479
/**
419-
* Reindexes $rows from a finder by their primary KEY_AS_FILENAME
480+
* Reindexes $rows from a finder by their primary key
420481
* Mostly used for consistent return format when no relations are requested
421482
* If multiple rows have the same primary (e.g. a join) it returns the originals
422483
*
423484
* @param array $rows Array of rows from the finder
424485
*
425486
* @return array
426487
*/
427-
protected function simpleReindex($rows): array
488+
public function simpleReindex($rows): array
428489
{
429490
if (empty($rows))
430491
{

tests/database/RelationsTest.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ public function testReindex()
2020
$this->assertEquals([1, 3, 4], array_keys($factories));
2121
}
2222

23+
public function testNotReindex()
24+
{
25+
$factories = $this->factories->with(false)->reindex(false)->findAll();
26+
27+
$this->assertEquals([0, 1, 2], array_keys($factories));
28+
}
29+
2330
public function testWithExplicit()
2431
{
2532
$worker = $this->workers->with('factories')->find(1);
@@ -48,7 +55,7 @@ public function testNestedRelations()
4855
{
4956
$servicer = $this->servicers->with('machines')->find(1);
5057
$factory = $this->factories->with(false)->find(1);
51-
58+
5259
$this->assertEquals($factory, $servicer->machines[1]->factory);
5360
}
5461

@@ -60,4 +67,16 @@ public function testNestedRelationsNotTooDeep()
6067
$this->assertEquals($factory, $factories[1]->machines[1]->factory);
6168
$this->assertObjectNotHasAttribute('machines', $factories[1]->machines[1]->factory);
6269
}
70+
71+
public function testBelongsToNested()
72+
{
73+
$machines = $this->machines->findAll();
74+
$factories = $this->factories->with(false)->findAll();
75+
76+
$this->assertEquals($factories[1], $machines[1]->factory);
77+
78+
$this->assertEquals($factories[1], $machines[3]->factory);
79+
80+
$this->assertEquals($factories[3], $machines[6]->factory);
81+
}
6382
}

0 commit comments

Comments
 (0)