Skip to content

Commit d464eff

Browse files
authored
Merge pull request #806 from michalsn/fix/identities-fetching
fix: UserModel::assignIdentities() always produces a DB query
2 parents 85cd604 + e3f4d8f commit d464eff

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed

phpstan.neon.dist

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ parameters:
1212
ignoreErrors:
1313
- '#Call to an undefined method CodeIgniter\\Database\\ConnectionInterface::[A-Za-z].+\(\)#'
1414
- '#Cannot access property [\$a-z_]+ on (array|object)#'
15-
-
15+
- '#Call to an undefined method CodeIgniter\\Shield\\Models\\UserModel::getLastQuery\(\)#'
16+
-
1617
message: '#Call to deprecated function random_string\(\):#'
1718
paths:
1819
- src/Authentication/Actions/Email2FA.php

src/Entities/User.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ public function getIdentities(string $type = 'all'): array
117117
return $identities;
118118
}
119119

120+
public function setIdentities(array $identities): void
121+
{
122+
$this->identities = $identities;
123+
}
124+
120125
/**
121126
* Creates a new identity for this user with an email/password
122127
* combination.

src/Models/UserModel.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ protected function fetchIdentities(array $data): array
113113
*/
114114
private function assignIdentities(array $data, array $identities): array
115115
{
116-
$mappedUsers = [];
116+
$mappedUsers = [];
117+
$userIdentities = [];
117118

118119
$users = $data['singleton'] ? [$data['data']] : $data['data'];
119120

@@ -122,15 +123,17 @@ private function assignIdentities(array $data, array $identities): array
122123
}
123124
unset($users);
124125

125-
// Now assign the identities to the user
126+
// Now group the identities by user
126127
foreach ($identities as $identity) {
127-
$userId = $identity->user_id;
128-
129-
$newIdentities = $mappedUsers[$userId]->identities;
130-
$newIdentities[] = $identity;
128+
$userIdentities[$identity->user_id][] = $identity;
129+
}
130+
unset($identities);
131131

132-
$mappedUsers[$userId]->identities = $newIdentities;
132+
// Now assign the identities to the user
133+
foreach ($userIdentities as $userId => $identityArray) {
134+
$mappedUsers[$userId]->identities = $identityArray;
133135
}
136+
unset($userIdentities);
134137

135138
return $mappedUsers;
136139
}

tests/Unit/UserTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,35 @@ public function testModelFindByIdWithIdentities(): void
8787
$this->assertCount(2, $user->identities);
8888
}
8989

90+
public function testModelFindAllWithIdentitiesWhereInQuery(): void
91+
{
92+
fake(UserIdentityModel::class, ['user_id' => $this->user->id, 'type' => 'password']);
93+
fake(UserIdentityModel::class, ['user_id' => $this->user->id, 'type' => 'access_token']);
94+
95+
// Grab the user again, using the model's identity helper
96+
$users = model(UserModel::class)->withIdentities()->findAll();
97+
98+
$identities = [];
99+
100+
foreach ($users as $user) {
101+
if ($user->id !== $this->user->id) {
102+
continue;
103+
}
104+
105+
$identities = $user->identities;
106+
107+
// Check the last query and see if a proper type of query was used
108+
$query = (string) model(UserModel::class)->getLastQuery();
109+
$this->assertMatchesRegularExpression(
110+
'/WHERE\s+.*\s+IN\s+\([^)]+\)/i',
111+
$query,
112+
'Identities were not obtained with the single query (missing "WHERE ... IN" condition)'
113+
);
114+
}
115+
116+
$this->assertCount(2, $identities);
117+
}
118+
90119
public function testModelFindByIdWithIdentitiesUserNotExists(): void
91120
{
92121
$user = model(UserModel::class)->where('active', 0)->withIdentities()->findById(1);

0 commit comments

Comments
 (0)