Skip to content

Commit 4767584

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into 4.5
2 parents abddd1d + 3266127 commit 4767584

File tree

11 files changed

+165
-65
lines changed

11 files changed

+165
-65
lines changed

admin/css/debug-toolbar/_theme-dark.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,6 @@
150150
.timer {
151151
background-color: $g-orange;
152152
}
153-
154-
.timeline-parent-open td {
155-
color: $t-dark;
156-
}
157153
}
158154
}
159155

contributing/css.md

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ the official website: <https://sass-lang.com/install>
99
Open your terminal, and navigate to CodeIgniter's root folder. To
1010
generate the CSS file, use the following command:
1111

12-
`sass --no-source-map admin/css/debug-toolbar/toolbar.scss system/Debug/Toolbar/Views/toolbar.css`
12+
```console
13+
sass --no-source-map admin/css/debug-toolbar/toolbar.scss system/Debug/Toolbar/Views/toolbar.css`
14+
```
1315

1416
Details:
1517
- `--no-source-map` is an option which prevents sourcemap files from being generated
@@ -18,23 +20,4 @@ Details:
1820

1921
## Color scheme
2022

21-
**Themes**
22-
23-
Dark: `#252525` / `rgb(37, 37, 37)`
24-
Light: `#FFFFFF` / `rgb(255, 255, 255)`
25-
26-
**Glossy colors**
27-
28-
Blue: `#5BC0DE` / `rgb(91, 192, 222)`
29-
Gray: `#434343` / `rgb(67, 67, 67)`
30-
Green: `#9ACE25` / `rgb(154, 206, 37)`
31-
Orange: `#DD8615` / `rgb(221, 134, 21)`
32-
Red: `#DD4814` / `rgb(221, 72, 20)`
33-
34-
**Matt colors**
35-
36-
Blue: `#D8EAF0` / `rgb(216, 234, 240)`
37-
Gray: `#DFDFDF` / `rgb(223, 223, 223)`
38-
Green: `#DFF0D8` / `rgb(223, 240, 216)`
39-
Orange: `#FDC894` / `rgb(253, 200, 148)`
40-
Red: `#EF9090` / `rgb(239, 144, 144)`
23+
See [_graphic-charter.scss](../admin/css/debug-toolbar/_graphic-charter.scss).

system/Debug/Toolbar/Views/toolbar.css

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,6 @@
532532
#debug-bar .timeline .timer {
533533
background-color: #DD8615;
534534
}
535-
#debug-bar .timeline .timeline-parent-open td {
536-
color: #252525;
537-
}
538535
.debug-view.show-view {
539536
border-color: #DD8615;
540537
}
@@ -647,9 +644,6 @@
647644
#toolbarContainer.dark #debug-bar .timeline .timer {
648645
background-color: #DD8615;
649646
}
650-
#toolbarContainer.dark #debug-bar .timeline .timeline-parent-open td {
651-
color: #252525;
652-
}
653647
#toolbarContainer.dark .debug-view.show-view {
654648
border-color: #DD8615;
655649
}

system/Validation/Validation.php

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,14 @@ public function run(?array $data = null, ?string $group = null, ?string $dbGroup
168168
}
169169

170170
if (strpos($field, '*') !== false) {
171-
$values = array_filter(array_flatten_with_dots($data), static fn ($key) => preg_match(
172-
'/^'
173-
. str_replace(['\.\*', '\*\.'], ['\..+', '.+\.'], preg_quote($field, '/'))
174-
. '$/',
175-
$key
176-
), ARRAY_FILTER_USE_KEY);
171+
$flattenedArray = array_flatten_with_dots($data);
172+
173+
$values = array_filter(
174+
$flattenedArray,
175+
static fn ($key) => preg_match(self::getRegex($field), $key),
176+
ARRAY_FILTER_USE_KEY
177+
);
178+
177179
// if keys not found
178180
$values = $values ?: [$field => null];
179181
} else {
@@ -211,6 +213,20 @@ public function run(?array $data = null, ?string $group = null, ?string $dbGroup
211213
return false;
212214
}
213215

216+
/**
217+
* Returns regex pattern for key with dot array syntax.
218+
*/
219+
private static function getRegex(string $field): string
220+
{
221+
return '/\A'
222+
. str_replace(
223+
['\.\*', '\*\.'],
224+
['\.[^.]+', '[^.]+\.'],
225+
preg_quote($field, '/')
226+
)
227+
. '\z/';
228+
}
229+
214230
/**
215231
* Runs the validation process, returning true or false determining whether
216232
* validation was successful or not.
@@ -816,9 +832,7 @@ private function retrievePlaceholders(string $rule, array $data): array
816832
*/
817833
public function hasError(string $field): bool
818834
{
819-
$pattern = '/^' . str_replace('\.\*', '\..+', preg_quote($field, '/')) . '$/';
820-
821-
return (bool) preg_grep($pattern, array_keys($this->getErrors()));
835+
return (bool) preg_grep(self::getRegex($field), array_keys($this->getErrors()));
822836
}
823837

824838
/**
@@ -831,10 +845,11 @@ public function getError(?string $field = null): string
831845
$field = array_key_first($this->rules);
832846
}
833847

834-
$errors = array_filter($this->getErrors(), static fn ($key) => preg_match(
835-
'/^' . str_replace(['\.\*', '\*\.'], ['\..+', '.+\.'], preg_quote($field, '/')) . '$/',
836-
$key
837-
), ARRAY_FILTER_USE_KEY);
848+
$errors = array_filter(
849+
$this->getErrors(),
850+
static fn ($key) => preg_match(self::getRegex($field), $key),
851+
ARRAY_FILTER_USE_KEY
852+
);
838853

839854
return $errors === [] ? '' : implode("\n", $errors);
840855
}

tests/system/Validation/ValidationTest.php

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,17 +1206,17 @@ public function testRulesForSingleRuleWithAsteriskWillReturnError(): void
12061206
$request = new IncomingRequest($config, new URI(), 'php://input', new UserAgent());
12071207

12081208
$this->validation->setRules([
1209-
'id_user.*' => 'numeric',
1210-
'name_user.*' => 'alpha',
1211-
'contacts.*.name' => 'required',
1209+
'id_user.*' => 'numeric',
1210+
'name_user.*' => 'alpha',
1211+
'contacts.friends.*.name' => 'required',
12121212
]);
12131213

12141214
$this->validation->withRequest($request->withMethod('post'))->run();
12151215
$this->assertSame([
12161216
'id_user.0' => 'The id_user.* field must contain only numbers.',
12171217
'name_user.0' => 'The name_user.* field may only contain alphabetical characters.',
12181218
'name_user.2' => 'The name_user.* field may only contain alphabetical characters.',
1219-
'contacts.friends.0.name' => 'The contacts.*.name field is required.',
1219+
'contacts.friends.0.name' => 'The contacts.friends.*.name field is required.',
12201220
], $this->validation->getErrors());
12211221

12221222
$this->assertSame(
@@ -1225,8 +1225,8 @@ public function testRulesForSingleRuleWithAsteriskWillReturnError(): void
12251225
$this->validation->getError('name_user.*')
12261226
);
12271227
$this->assertSame(
1228-
'The contacts.*.name field is required.',
1229-
$this->validation->getError('contacts.*.name')
1228+
'The contacts.friends.*.name field is required.',
1229+
$this->validation->getError('contacts.friends.*.name')
12301230
);
12311231
}
12321232

@@ -1323,17 +1323,17 @@ public function testTranslatedLabelTagReplacement(): void
13231323
}
13241324

13251325
/**
1326-
* @dataProvider provideDotNotationOnIfExistRule
1326+
* @dataProvider provideIfExistRuleWithAsterisk
13271327
*
13281328
* @see https://github.com/codeigniter4/CodeIgniter4/issues/4521
13291329
*/
1330-
public function testDotNotationOnIfExistRule(bool $expected, array $rules, array $data): void
1330+
public function testIfExistRuleWithAsterisk(bool $expected, array $rules, array $data): void
13311331
{
13321332
$actual = $this->validation->setRules($rules)->run($data);
13331333
$this->assertSame($expected, $actual);
13341334
}
13351335

1336-
public static function provideDotNotationOnIfExistRule(): iterable
1336+
public static function provideIfExistRuleWithAsterisk(): iterable
13371337
{
13381338
yield 'dot-on-end-fail' => [
13391339
false,
@@ -1708,7 +1708,7 @@ public function testRuleWithLeadingAsterisk(): void
17081708
/**
17091709
* @see https://github.com/codeigniter4/CodeIgniter4/issues/5942
17101710
*/
1711-
public function testRequireWithoutWithWildCard(): void
1711+
public function testRequireWithoutWithAsterisk(): void
17121712
{
17131713
$data = [
17141714
'a' => [
@@ -1726,4 +1726,50 @@ public function testRequireWithoutWithWildCard(): void
17261726
$this->validation->getError('a.1.c')
17271727
);
17281728
}
1729+
1730+
/**
1731+
* @see https://github.com/codeigniter4/CodeIgniter4/issues/8128
1732+
*/
1733+
public function testRuleWithAsteriskToMultiDimensionalArray(): void
1734+
{
1735+
$data = [
1736+
'contacts' => [
1737+
'name' => 'Joe Smith',
1738+
'just' => [
1739+
'friends' => [
1740+
[
1741+
'name' => 'Fred Flinstone',
1742+
],
1743+
[
1744+
'name' => 'Wilma',
1745+
],
1746+
],
1747+
],
1748+
],
1749+
];
1750+
1751+
$this->validation->setRules(
1752+
['contacts.just.friends.*.name' => 'required|max_length[1]']
1753+
);
1754+
$this->assertFalse($this->validation->run($data));
1755+
$this->assertSame(
1756+
[
1757+
'contacts.just.friends.0.name' => 'The contacts.just.friends.*.name field cannot exceed 1 characters in length.',
1758+
'contacts.just.friends.1.name' => 'The contacts.just.friends.*.name field cannot exceed 1 characters in length.',
1759+
],
1760+
$this->validation->getErrors()
1761+
);
1762+
1763+
$this->validation->reset();
1764+
$this->validation->setRules(
1765+
['contacts.*.name' => 'required|max_length[1]']
1766+
);
1767+
$this->assertFalse($this->validation->run($data));
1768+
$this->assertSame(
1769+
// The data for `contacts.*.name` does not exist. So it is interpreted
1770+
// as `null`, and this error message returns.
1771+
['contacts.*.name' => 'The contacts.*.name field is required.'],
1772+
$this->validation->getErrors()
1773+
);
1774+
}
17291775
}

user_guide_src/source/changelogs/v4.4.4.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ Release Date: Unreleased
1414
BREAKING
1515
********
1616

17+
Validation with Dot Array Syntax
18+
================================
19+
20+
A validation rule with the wildcard ``*`` now validates only data in correct
21+
dimensions as "dot array syntax".
22+
See :ref:`Upgrading <upgrade-444-validation-with-dot-array-syntax>` for details.
23+
1724
***************
1825
Message Changes
1926
***************

user_guide_src/source/installation/upgrade_444.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,25 @@ Mandatory File Changes
2020
Breaking Changes
2121
****************
2222

23+
.. _upgrade-444-validation-with-dot-array-syntax:
24+
25+
Validation with Dot Array Syntax
26+
================================
27+
28+
If you are using :ref:`dot array syntax <validation-dot-array-syntax>` in validation
29+
rules, a bug where ``*`` would validate data in incorrect dimensions has been fixed.
30+
31+
In previous versions, the rule key ``contacts.*.name`` captured data with any
32+
level like ``contacts.*.name``, ``contacts.*.*.name``, ``contacts.*.*.*.name``,
33+
etc., incorrectly.
34+
35+
The following code explains details:
36+
37+
.. literalinclude:: upgrade_444/001.php
38+
:lines: 2-
39+
40+
If you have code that depends on the bug, fix the the rule key.
41+
2342
*********************
2443
Breaking Enhancements
2544
*********************
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
use Config\Services;
4+
5+
$validation = Services::validation();
6+
7+
$data = [
8+
'contacts' => [
9+
'name' => 'Joe Smith',
10+
'just' => [
11+
'friends' => [
12+
['name' => 'SATO Taro'],
13+
['name' => 'Li Ming'],
14+
['name' => 'Heinz Müller'],
15+
],
16+
],
17+
],
18+
];
19+
20+
$validation->setRules(
21+
['contacts.*.name' => 'required|max_length[8]']
22+
);
23+
24+
$validation->run($data); // false
25+
26+
d($validation->getErrors());
27+
/*
28+
Before: Captured `contacts.*.*.*.name` incorrectly.
29+
[
30+
contacts.just.friends.0.name => "The contacts.*.name field cannot exceed 8 characters in length.",
31+
contacts.just.friends.2.name => "The contacts.*.name field cannot exceed 8 characters in length.",
32+
]
33+
34+
After: Captures no data for `contacts.*.name`.
35+
[
36+
contacts.*.name => string (38) "The contacts.*.name field is required.",
37+
]
38+
*/

user_guide_src/source/libraries/validation.rst

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ To give a labeled error message you can set up as:
325325
.. note:: ``setRules()`` will overwrite any rules that were set previously. To add more than one
326326
rule to an existing set of rules, use ``setRule()`` multiple times.
327327

328+
.. _validation-dot-array-syntax:
329+
328330
Setting Rules for Array Data
329331
============================
330332

@@ -339,6 +341,10 @@ You can use the ``*`` wildcard symbol to match any one level of the array:
339341
.. literalinclude:: validation/010.php
340342
:lines: 2-
341343

344+
.. note:: Prior to v4.4.4, due to a bug, the wildcard ``*`` validated data in incorrect
345+
dimensions. See :ref:`Upgrading <upgrade-444-validation-with-dot-array-syntax>`
346+
for details.
347+
342348
"dot array syntax" can also be useful when you have single dimension array data.
343349
For example, data returned by multi select dropdown:
344350

@@ -602,7 +608,7 @@ If you need to retrieve all error messages for failed fields, you can use the ``
602608

603609
If no errors exist, an empty array will be returned.
604610

605-
When using a wildcard, the error will point to a specific field, replacing the asterisk with the appropriate key/keys::
611+
When using a wildcard (``*``), the error will point to a specific field, replacing the asterisk with the appropriate key/keys::
606612

607613
// for data
608614
'contacts' => [
@@ -617,10 +623,10 @@ When using a wildcard, the error will point to a specific field, replacing the a
617623
]
618624

619625
// rule
620-
'contacts.*.name' => 'required'
626+
'contacts.friends.*.name' => 'required'
621627

622628
// error will be
623-
'contacts.friends.1.name' => 'The contacts.*.name field is required.'
629+
'contacts.friends.1.name' => 'The contacts.friends.*.name field is required.'
624630

625631
Getting a Single Error
626632
======================
@@ -864,7 +870,8 @@ alpha_numeric_punct No Fails if field contains anything other than
864870
alphanumeric, space, or this limited set of
865871
punctuation characters: ``~`` (tilde),
866872
``!`` (exclamation), ``#`` (number),
867-
``$`` (dollar), ``% (percent), & (ampersand),
873+
``$`` (dollar), ``%`` (percent),
874+
``&`` (ampersand),
868875
``*`` (asterisk), ``-`` (dash),
869876
``_`` (underscore), ``+`` (plus),
870877
``=`` (equals), ``|`` (vertical bar),

user_guide_src/source/libraries/validation/009.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* The data to test:
55
* [
66
* 'contacts' => [
7-
* 'name' => 'Joe Smith',
7+
* 'name' => 'Joe Smith',
88
* 'friends' => [
99
* [
1010
* 'name' => 'Fred Flinstone',
@@ -21,8 +21,3 @@
2121
$validation->setRules([
2222
'contacts.name' => 'required|max_length[60]',
2323
]);
24-
25-
// Fred Flintsone & Wilma
26-
$validation->setRules([
27-
'contacts.friends.name' => 'required|max_length[60]',
28-
]);

0 commit comments

Comments
 (0)