Skip to content

Commit 5ad816b

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into 4.3
Conflicts: tests/system/CLI/CommandRunnerTest.php
2 parents ec6e6a9 + 071cd04 commit 5ad816b

File tree

12 files changed

+135
-26
lines changed

12 files changed

+135
-26
lines changed

admin/framework/composer.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,18 @@
2424
"predis/predis": "^1.1 || ^2.0"
2525
},
2626
"suggest": {
27-
"ext-fileinfo": "Improves mime type detection for files"
27+
"ext-imagick": "If you use Image class ImageMagickHandler",
28+
"ext-simplexml": "If you format XML",
29+
"ext-mysqli": "If you use MySQL",
30+
"ext-oci8": "If you use Oracle Database",
31+
"ext-pgsql": "If you use PostgreSQL",
32+
"ext-sqlsrv": "If you use SQL Server",
33+
"ext-sqlite3": "If you use SQLite3",
34+
"ext-memcache": "If you use Cache class MemcachedHandler with Memcache",
35+
"ext-memcached": "If you use Cache class MemcachedHandler with Memcached",
36+
"ext-redis": "If you use Cache class RedisHandler",
37+
"ext-fileinfo": "Improves mime type detection for files",
38+
"ext-readline": "Improves CLI::input() usability"
2839
},
2940
"autoload": {
3041
"psr-4": {

system/Commands/Cache/ClearCache.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class ClearCache extends BaseCommand
4646
*
4747
* @var string
4848
*/
49-
protected $usage = 'cache:clear [driver]';
49+
protected $usage = 'cache:clear [<driver>]';
5050

5151
/**
5252
* the Command's Arguments

system/Commands/Help.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class Help extends BaseCommand
4848
*
4949
* @var string
5050
*/
51-
protected $usage = 'help command_name';
51+
protected $usage = 'help [<command_name>]';
5252

5353
/**
5454
* the Command's Arguments

system/Database/BaseBuilder.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ public function fromSubquery(BaseBuilder $from, string $alias): self
577577
{
578578
$table = $this->buildSubquery($from, true, $alias);
579579

580-
$this->trackAliases($table);
580+
$this->db->addTableAlias($alias);
581581
$this->QBFrom[] = $table;
582582

583583
return $this;
@@ -2944,7 +2944,7 @@ protected function buildSubquery($builder, bool $wrapped = false, string $alias
29442944
throw new DatabaseException('The subquery cannot be the same object as the main query object.');
29452945
}
29462946

2947-
$subquery = strtr($builder->getCompiledSelect(), "\n", ' ');
2947+
$subquery = strtr($builder->getCompiledSelect(false), "\n", ' ');
29482948

29492949
if ($wrapped) {
29502950
$subquery = '(' . $subquery . ')';

system/Database/BaseConnection.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,12 @@ public function table($tableName)
883883
*/
884884
public function newQuery(): BaseBuilder
885885
{
886-
return $this->table(',')->from([], true);
886+
// save table aliases
887+
$tempAliases = $this->aliasedTables;
888+
$builder = $this->table(',')->from([], true);
889+
$this->aliasedTables = $tempAliases;
890+
891+
return $builder;
887892
}
888893

889894
/**

system/Validation/Validation.php

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public function run(?array $data = null, ?string $group = null, ?string $dbGroup
162162
if (strpos($field, '*') !== false) {
163163
// Process multiple fields
164164
foreach ($values as $dotField => $value) {
165-
$this->processRules($dotField, $setup['label'] ?? $field, $value, $rules, $data);
165+
$this->processRules($dotField, $setup['label'] ?? $field, $value, $rules, $data, $field);
166166
}
167167
} else {
168168
// Process single field
@@ -195,10 +195,17 @@ public function check($value, string $rule, array $errors = []): bool
195195
*
196196
* @param array|string $value
197197
* @param array|null $rules
198-
* @param array $data
198+
* @param array $data The array of data to validate, with `DBGroup`.
199+
* @param string|null $originalField The original asterisk field name like "foo.*.bar".
199200
*/
200-
protected function processRules(string $field, ?string $label, $value, $rules = null, ?array $data = null): bool
201-
{
201+
protected function processRules(
202+
string $field,
203+
?string $label,
204+
$value,
205+
$rules = null,
206+
?array $data = null,
207+
?string $originalField = null
208+
): bool {
202209
if ($data === null) {
203210
throw new InvalidArgumentException('You must supply the parameter: data.');
204211
}
@@ -327,7 +334,8 @@ protected function processRules(string $field, ?string $label, $value, $rules =
327334
$field,
328335
$label,
329336
$param,
330-
(string) $value
337+
(string) $value,
338+
$originalField
331339
);
332340

333341
return false;
@@ -697,13 +705,21 @@ public function setError(string $field, string $error): ValidationInterface
697705
*
698706
* @param string|null $value The value that caused the validation to fail.
699707
*/
700-
protected function getErrorMessage(string $rule, string $field, ?string $label = null, ?string $param = null, ?string $value = null): string
701-
{
708+
protected function getErrorMessage(
709+
string $rule,
710+
string $field,
711+
?string $label = null,
712+
?string $param = null,
713+
?string $value = null,
714+
?string $originalField = null
715+
): string {
702716
$param ??= '';
703717

704718
// Check if custom message has been defined by user
705719
if (isset($this->customErrors[$field][$rule])) {
706720
$message = lang($this->customErrors[$field][$rule]);
721+
} elseif (null !== $originalField && isset($this->customErrors[$originalField][$rule])) {
722+
$message = lang($this->customErrors[$originalField][$rule]);
707723
} else {
708724
// Try to grab a localized version of the message...
709725
// lang() will return the rule name back if not found,

tests/AutoReview/ComposerJsonTest.php

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,30 @@
2424
*/
2525
final class ComposerJsonTest extends TestCase
2626
{
27-
public function testFrameworkRequireIsTheSameWithDevRequire(): void
27+
private array $devComposer;
28+
private array $frameworkComposer;
29+
30+
protected function setUp(): void
2831
{
29-
$devComposer = $this->getComposerJson(dirname(__DIR__, 2) . '/composer.json');
30-
$frameworkComposer = $this->getComposerJson(dirname(__DIR__, 2) . '/admin/framework/composer.json');
32+
parent::setUp();
33+
34+
$this->devComposer = $this->getComposerJson(dirname(__DIR__, 2) . '/composer.json');
35+
$this->frameworkComposer = $this->getComposerJson(dirname(__DIR__, 2) . '/admin/framework/composer.json');
36+
}
3137

38+
public function testFrameworkRequireIsTheSameWithDevRequire(): void
39+
{
3240
$this->assertSame(
33-
$devComposer['require'],
34-
$frameworkComposer['require'],
41+
$this->devComposer['require'],
42+
$this->frameworkComposer['require'],
3543
'The framework\'s "require" section is not updated with the main composer.json.'
3644
);
3745
}
3846

3947
public function testFrameworkRequireDevIsTheSameWithDevRequireDev(): void
4048
{
41-
$devComposer = $this->getComposerJson(dirname(__DIR__, 2) . '/composer.json');
42-
$frameworkComposer = $this->getComposerJson(dirname(__DIR__, 2) . '/admin/framework/composer.json');
43-
44-
$devRequireDev = $devComposer['require-dev'];
45-
$fwRequireDev = $frameworkComposer['require-dev'];
49+
$devRequireDev = $this->devComposer['require-dev'];
50+
$fwRequireDev = $this->frameworkComposer['require-dev'];
4651

4752
foreach ($devRequireDev as $dependency => $expectedVersion) {
4853
if (! isset($fwRequireDev[$dependency])) {
@@ -62,6 +67,15 @@ public function testFrameworkRequireDevIsTheSameWithDevRequireDev(): void
6267
}
6368
}
6469

70+
public function testFrameworkSuggestIsTheSameWithDevSuggest(): void
71+
{
72+
$this->assertSame(
73+
$this->devComposer['suggest'],
74+
$this->frameworkComposer['suggest'],
75+
'The framework\'s "suggest" section is not updated with the main composer.json.'
76+
);
77+
}
78+
6579
private function getComposerJson(string $path): array
6680
{
6781
try {

tests/system/Database/Builder/PrefixTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace CodeIgniter\Database\Builder;
1313

14+
use CodeIgniter\Database\BaseBuilder;
1415
use CodeIgniter\Test\CIUnitTestCase;
1516
use CodeIgniter\Test\Mock\MockConnection;
1617

@@ -49,4 +50,40 @@ public function testPrefixesSetOnTableNamesWithWhereClause()
4950
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
5051
$this->assertSame($expectedBinds, $builder->getBinds());
5152
}
53+
54+
public function testPrefixWithSubquery(): void
55+
{
56+
$expected = <<<'NOWDOC'
57+
SELECT "u"."id", "u"."name", (SELECT 1 FROM "ci_users" "sub" WHERE "sub"."id" = "u"."id") "one"
58+
FROM "ci_users" "u"
59+
WHERE "u"."id" = 1
60+
NOWDOC;
61+
62+
$subquery = $this->db->table('users sub')
63+
->select('1', false)
64+
->where('sub.id = u.id');
65+
66+
$builder = $this->db->table('users u')
67+
->select('u.id, u.name')
68+
->selectSubquery($subquery, 'one')
69+
->where('u.id', 1);
70+
71+
$this->assertSame($expected, $builder->getCompiledSelect());
72+
}
73+
74+
public function testPrefixWithNewQuery(): void
75+
{
76+
$expectedSQL = <<<'NOWDOC'
77+
SELECT "users_1"."id", "name"
78+
FROM (SELECT "u"."id", "u"."name" FROM "ci_users" "u") "users_1"
79+
WHERE "users_1"."id" > 10
80+
NOWDOC;
81+
82+
$subquery = (new BaseBuilder('users u', $this->db))->select('u.id, u.name');
83+
$builder = $this->db->newQuery()->fromSubquery($subquery, 'users_1')
84+
->select('users_1.id, name')
85+
->where('users_1.id > ', 10);
86+
87+
$this->assertSame($expectedSQL, $builder->getCompiledSelect());
88+
}
5289
}

tests/system/Validation/ValidationTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,28 @@ public function testRunGroupWithCustomErrorMessage(): void
463463
], $this->validation->getErrors());
464464
}
465465

466+
/**
467+
* @see https://github.com/codeigniter4/CodeIgniter4/issues/6245
468+
*/
469+
public function testRunWithCustomErrorsAndAsteriskField(): void
470+
{
471+
$data = [
472+
'foo' => [
473+
['bar' => null],
474+
['bar' => null],
475+
],
476+
];
477+
$this->validation->setRules(
478+
['foo.*.bar' => ['label' => 'foo bar', 'rules' => 'required']],
479+
['foo.*.bar' => ['required' => 'Required']]
480+
);
481+
$this->validation->run($data);
482+
$this->assertSame([
483+
'foo.0.bar' => 'Required',
484+
'foo.1.bar' => 'Required',
485+
], $this->validation->getErrors());
486+
}
487+
466488
/**
467489
* @dataProvider rulesSetupProvider
468490
*

user_guide_src/source/changelogs/v4.2.5.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ BREAKING
1414

1515
- The method signature of ``BaseConnection::tableExists()`` has been changed. A second optional parameter ``$cached`` was added. This directs whether to use cache data or not. Default is ``true``, use cache data.
1616
- The abstract method signature of ``BaseBuilder::_listTables()`` has been changed. A second optional parameter ``$tableName`` was added. Providing a table name will generate SQL listing only that table.
17+
- The method signature of ``Validation::processRules()`` and ``Validation::getErrorMessage()`` have been changed. Both of these methods add new ``$originalField`` parameter.
1718

1819
Enhancements
1920
************
@@ -32,5 +33,6 @@ none.
3233

3334
Bugs Fixed
3435
**********
36+
- When using subqueries in the main query, prefixes are added to the table alias.
3537

3638
See the repo's `CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_ for a complete list of bugs fixed.

user_guide_src/source/database/metadata.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,11 @@ The following data is available from this function if supported by your
101101
database:
102102

103103
- name - column name
104-
- max_length - maximum length of the column
105-
- primary_key - 1 if the column is a primary key
106104
- type - the type of the column
105+
- max_length - maximum length of the column
106+
- primary_key - integer ``1`` if the column is a primary key (all integer ``1``, even if there are multiple primary keys), otherwise integer ``0``
107+
- nullable - boolean ``true`` if the column is nullable, otherwise boolean ``false``
108+
- default - the default value
107109

108110
List the Indexes in a Table
109111
===========================

user_guide_src/source/general/managing_apps.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ directory. It is possible, however, to have multiple sets of
88
applications that share a single CodeIgniter installation, or even to
99
rename or relocate your application directory.
1010

11-
.. important:: When you installed CodeIgniter v4.1.9 or before, and if there are ``App\\`` and ``Config\\`` namespaces in your ``/composer.json``'s ``autoload.psr-4`` like the following, you need to remove these lines, and run ``composer dump-autolod``.
11+
.. important:: When you installed CodeIgniter v4.1.9 or before, and if there are ``App\\`` and ``Config\\`` namespaces in your ``/composer.json``'s ``autoload.psr-4`` like the following, you need to remove these lines, and run ``composer dump-autoload``.
1212

1313
.. code-block:: text
1414

0 commit comments

Comments
 (0)