Skip to content

Commit 8a94ce6

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into 4.7
2 parents fca548d + bc62d40 commit 8a94ce6

File tree

15 files changed

+202
-84
lines changed

15 files changed

+202
-84
lines changed

.github/workflows/test-scss.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
uses: actions/checkout@v5
3737

3838
- name: Setup Node
39-
uses: actions/setup-node@v4.0.0
39+
uses: actions/setup-node@v5.0.0
4040
with:
4141
# node version based on dart-sass test workflow
4242
node-version: 16

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"phpunit/phpcov": "^9.0.2 || ^10.0",
2929
"phpunit/phpunit": "^10.5.16 || ^11.2",
3030
"predis/predis": "^3.0",
31-
"rector/rector": "2.1.4",
31+
"rector/rector": "2.1.5",
3232
"shipmonk/phpstan-baseline-per-identifier": "^2.0"
3333
},
3434
"replace": {

rector.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
use Rector\Php70\Rector\FuncCall\RandomFunctionRector;
3636
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
3737
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
38+
use Rector\PHPUnit\CodeQuality\Rector\Class_\AddParamTypeFromDependsRector;
3839
use Rector\PHPUnit\CodeQuality\Rector\Class_\RemoveDataProviderParamKeysRector;
3940
use Rector\PHPUnit\CodeQuality\Rector\Class_\YieldDataProviderRector;
4041
use Rector\Privatization\Rector\Property\PrivatizeFinalClassPropertyRector;
@@ -170,6 +171,9 @@
170171
CompactToVariablesRector::class,
171172

172173
RemoveDataProviderParamKeysRector::class,
174+
175+
// buggy on no depends, @see https://github.com/rectorphp/rector-phpunit/pull/537
176+
AddParamTypeFromDependsRector::class,
173177
])
174178
// auto import fully qualified class names
175179
->withImportNames(removeUnusedImports: true)

system/BaseModel.php

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -909,22 +909,7 @@ public function insertBatch(?array $set = null, ?bool $escape = null, int $batch
909909

910910
if (is_array($set)) {
911911
foreach ($set as &$row) {
912-
// If $row is using a custom class with public or protected
913-
// properties representing the collection elements, we need to grab
914-
// them as an array.
915-
if (is_object($row) && ! $row instanceof stdClass) {
916-
$row = $this->objectToArray($row, false, true);
917-
}
918-
919-
// If it's still a stdClass, go ahead and convert to
920-
// an array so doProtectFields and other model methods
921-
// don't have to do special checks.
922-
if (is_object($row)) {
923-
$row = (array) $row;
924-
}
925-
926-
// Convert any Time instances to appropriate $dateFormat
927-
$row = $this->timeToString($row);
912+
$row = $this->transformDataRowToArray($row);
928913

929914
// Validate every row.
930915
if (! $this->skipValidation && ! $this->validate($row)) {
@@ -1051,21 +1036,7 @@ public function updateBatch(?array $set = null, ?string $index = null, int $batc
10511036
{
10521037
if (is_array($set)) {
10531038
foreach ($set as &$row) {
1054-
// If $row is using a custom class with public or protected
1055-
// properties representing the collection elements, we need to grab
1056-
// them as an array.
1057-
if (is_object($row) && ! $row instanceof stdClass) {
1058-
// For updates the index field is needed even if it is not changed.
1059-
// So set $onlyChanged to false.
1060-
$row = $this->objectToArray($row, false, true);
1061-
}
1062-
1063-
// If it's still a stdClass, go ahead and convert to
1064-
// an array so doProtectFields and other model methods
1065-
// don't have to do special checks.
1066-
if (is_object($row)) {
1067-
$row = (array) $row;
1068-
}
1039+
$row = $this->transformDataRowToArray($row);
10691040

10701041
// Validate data before saving.
10711042
if (! $this->skipValidation && ! $this->validate($row)) {
@@ -1220,7 +1191,9 @@ public function replace(?array $row = null, bool $returnSQL = false)
12201191
return false;
12211192
}
12221193

1223-
$row = $this->setUpdatedField((array) $row, $this->setDate());
1194+
$row = (array) $row;
1195+
$row = $this->setCreatedField($row, $this->setDate());
1196+
$row = $this->setUpdatedField($row, $this->setDate());
12241197

12251198
return $this->doReplace($row, $returnSQL);
12261199
}
@@ -1694,6 +1667,52 @@ protected function trigger(string $event, array $eventData)
16941667
return $eventData;
16951668
}
16961669

1670+
/**
1671+
* If the model is using casts, this will convert the data
1672+
* in $row according to the rules defined in `$casts`.
1673+
*
1674+
* @param object|row_array|null $row Row data
1675+
*
1676+
* @return object|row_array|null Converted row data
1677+
*
1678+
* @used-by insertBatch()
1679+
* @used-by updateBatch()
1680+
*
1681+
* @throws ReflectionException
1682+
* @deprecated Since 4.6.4, temporary solution - will be removed in 4.7
1683+
*/
1684+
protected function transformDataRowToArray(array|object|null $row): array|object|null
1685+
{
1686+
// If casts are used, convert the data first
1687+
if ($this->useCasts()) {
1688+
if (is_array($row)) {
1689+
$row = $this->converter->toDataSource($row);
1690+
} elseif ($row instanceof stdClass) {
1691+
$row = (array) $row;
1692+
$row = $this->converter->toDataSource($row);
1693+
} elseif ($row instanceof Entity) {
1694+
$row = $this->converter->extract($row);
1695+
} elseif (is_object($row)) {
1696+
$row = $this->converter->extract($row);
1697+
}
1698+
} elseif (is_object($row) && ! $row instanceof stdClass) {
1699+
// If $row is using a custom class with public or protected
1700+
// properties representing the collection elements, we need to grab
1701+
// them as an array.
1702+
$row = $this->objectToArray($row, false, true);
1703+
}
1704+
1705+
// If it's still a stdClass, go ahead and convert to
1706+
// an array so doProtectFields and other model methods
1707+
// don't have to do special checks.
1708+
if (is_object($row)) {
1709+
$row = (array) $row;
1710+
}
1711+
1712+
// Convert any Time instances to appropriate $dateFormat
1713+
return $this->timeToString($row);
1714+
}
1715+
16971716
/**
16981717
* Sets the return type of the results to be as an associative array.
16991718
*

system/Commands/Utilities/Routes/AutoRouterImproved/AutoRouteCollector.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public function get(): array
9999
*
100100
* @return list<array<string, array|string>>
101101
*/
102-
private function addFilters($routes)
102+
private function addFilters(array $routes): array
103103
{
104104
$filterCollector = new FilterCollector(true);
105105

system/Database/BaseBuilder.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3257,18 +3257,17 @@ protected function compileOrderBy(): string
32573257
{
32583258
if (is_array($this->QBOrderBy) && $this->QBOrderBy !== []) {
32593259
foreach ($this->QBOrderBy as &$orderBy) {
3260+
if (is_string($orderBy)) {
3261+
continue;
3262+
}
32603263
if ($orderBy['escape'] !== false && ! $this->isLiteral($orderBy['field'])) {
32613264
$orderBy['field'] = $this->db->protectIdentifiers($orderBy['field']);
32623265
}
32633266

32643267
$orderBy = $orderBy['field'] . $orderBy['direction'];
32653268
}
32663269

3267-
return $this->QBOrderBy = "\nORDER BY " . implode(', ', $this->QBOrderBy);
3268-
}
3269-
3270-
if (is_string($this->QBOrderBy)) {
3271-
return $this->QBOrderBy;
3270+
return "\nORDER BY " . implode(', ', $this->QBOrderBy);
32723271
}
32733272

32743273
return '';

tests/system/Config/FactoriesTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ public function testGetComponentInstances(): array
460460
* }
461461
*/
462462
#[Depends('testGetComponentInstances')]
463-
public function testSetComponentInstances(array $data)
463+
public function testSetComponentInstances(array $data): array
464464
{
465465
$before = Factories::getComponentInstances('config');
466466
$this->assertSame(['options' => [], 'aliases' => [], 'instances' => []], $before);

tests/system/Database/Builder/SelectTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,4 +407,24 @@ public function testSelectResetQuery(): void
407407
str_replace("\n", ' ', $sql),
408408
);
409409
}
410+
411+
/**
412+
* @see https://github.com/codeigniter4/CodeIgniter4/issues/9696
413+
*/
414+
public function testGetCompiledSelect(): void
415+
{
416+
$builder = new BaseBuilder('users', $this->db);
417+
418+
$builder->select('name, role')->orderBy('name', 'desc');
419+
420+
$expected = 'SELECT "name", "role" FROM "users" ORDER BY "name" DESC';
421+
422+
$this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect(false)));
423+
424+
$builder->orderBy('role', 'desc');
425+
426+
$expected = 'SELECT "name", "role" FROM "users" ORDER BY "name" DESC, "role" DESC';
427+
428+
$this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect()));
429+
}
410430
}

tests/system/Database/Live/OCI8/CallStoredProcedureTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ protected function setUp(): void
3838

3939
public function testCallPackageProcedure(): void
4040
{
41-
$result = 0;
41+
$result = '0';
4242

4343
$this->db->storedProcedure('calculator.plus', [
4444
[
@@ -60,7 +60,7 @@ public function testCallPackageProcedure(): void
6060

6161
public function testCallStoredProcedure(): void
6262
{
63-
$result = 0;
63+
$result = '0';
6464

6565
$this->db->storedProcedure('plus', [
6666
[

tests/system/Models/InsertModelTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use stdClass;
2323
use Tests\Support\Entity\User;
2424
use Tests\Support\Models\JobModel;
25+
use Tests\Support\Models\UserCastsTimestampModel;
2526
use Tests\Support\Models\UserModel;
2627
use Tests\Support\Models\UserObjModel;
2728
use Tests\Support\Models\WithoutAutoIncrementModel;
@@ -376,4 +377,34 @@ public function testInsertWithDefaultValue(): void
376377
$id = $this->model->getInsertID();
377378
$this->assertSame($entity->country, $this->model->find($id)->country);
378379
}
380+
381+
public function testInsertBatchWithCasts(): void
382+
{
383+
$userData = [
384+
[
385+
'name' => 'Smriti',
386+
'email' => [
387+
'personal' => '[email protected]',
388+
'work' => '[email protected]',
389+
],
390+
'country' => 'India',
391+
],
392+
[
393+
'name' => 'Rahul',
394+
'email' => [
395+
'personal' => '[email protected]',
396+
'work' => '[email protected]',
397+
],
398+
'country' => 'India',
399+
],
400+
];
401+
$this->createModel(UserCastsTimestampModel::class);
402+
403+
$numRows = $this->model->insertBatch($userData); // @phpstan-ignore argument.type
404+
405+
$this->assertSame(2, $numRows);
406+
407+
$this->seeInDatabase('user', ['email' => json_encode($userData[0]['email'])]);
408+
$this->seeInDatabase('user', ['email' => json_encode($userData[1]['email'])]);
409+
}
379410
}

0 commit comments

Comments
 (0)