Merge remote-tracking branch 'upstream/develop' into 4.5

This commit is contained in:
kenjis 2023-11-03 09:38:11 +09:00
commit 47675842c4
No known key found for this signature in database
GPG Key ID: BD254878922AF198
11 changed files with 165 additions and 65 deletions

View File

@ -150,10 +150,6 @@
.timer {
background-color: $g-orange;
}
.timeline-parent-open td {
color: $t-dark;
}
}
}

View File

@ -9,7 +9,9 @@ the official website: <https://sass-lang.com/install>
Open your terminal, and navigate to CodeIgniter's root folder. To
generate the CSS file, use the following command:
`sass --no-source-map admin/css/debug-toolbar/toolbar.scss system/Debug/Toolbar/Views/toolbar.css`
```console
sass --no-source-map admin/css/debug-toolbar/toolbar.scss system/Debug/Toolbar/Views/toolbar.css`
```
Details:
- `--no-source-map` is an option which prevents sourcemap files from being generated
@ -18,23 +20,4 @@ Details:
## Color scheme
**Themes**
Dark: `#252525` / `rgb(37, 37, 37)`
Light: `#FFFFFF` / `rgb(255, 255, 255)`
**Glossy colors**
Blue: `#5BC0DE` / `rgb(91, 192, 222)`
Gray: `#434343` / `rgb(67, 67, 67)`
Green: `#9ACE25` / `rgb(154, 206, 37)`
Orange: `#DD8615` / `rgb(221, 134, 21)`
Red: `#DD4814` / `rgb(221, 72, 20)`
**Matt colors**
Blue: `#D8EAF0` / `rgb(216, 234, 240)`
Gray: `#DFDFDF` / `rgb(223, 223, 223)`
Green: `#DFF0D8` / `rgb(223, 240, 216)`
Orange: `#FDC894` / `rgb(253, 200, 148)`
Red: `#EF9090` / `rgb(239, 144, 144)`
See [_graphic-charter.scss](../admin/css/debug-toolbar/_graphic-charter.scss).

View File

@ -532,9 +532,6 @@
#debug-bar .timeline .timer {
background-color: #DD8615;
}
#debug-bar .timeline .timeline-parent-open td {
color: #252525;
}
.debug-view.show-view {
border-color: #DD8615;
}
@ -647,9 +644,6 @@
#toolbarContainer.dark #debug-bar .timeline .timer {
background-color: #DD8615;
}
#toolbarContainer.dark #debug-bar .timeline .timeline-parent-open td {
color: #252525;
}
#toolbarContainer.dark .debug-view.show-view {
border-color: #DD8615;
}

View File

@ -168,12 +168,14 @@ class Validation implements ValidationInterface
}
if (strpos($field, '*') !== false) {
$values = array_filter(array_flatten_with_dots($data), static fn ($key) => preg_match(
'/^'
. str_replace(['\.\*', '\*\.'], ['\..+', '.+\.'], preg_quote($field, '/'))
. '$/',
$key
), ARRAY_FILTER_USE_KEY);
$flattenedArray = array_flatten_with_dots($data);
$values = array_filter(
$flattenedArray,
static fn ($key) => preg_match(self::getRegex($field), $key),
ARRAY_FILTER_USE_KEY
);
// if keys not found
$values = $values ?: [$field => null];
} else {
@ -211,6 +213,20 @@ class Validation implements ValidationInterface
return false;
}
/**
* Returns regex pattern for key with dot array syntax.
*/
private static function getRegex(string $field): string
{
return '/\A'
. str_replace(
['\.\*', '\*\.'],
['\.[^.]+', '[^.]+\.'],
preg_quote($field, '/')
)
. '\z/';
}
/**
* Runs the validation process, returning true or false determining whether
* validation was successful or not.
@ -816,9 +832,7 @@ class Validation implements ValidationInterface
*/
public function hasError(string $field): bool
{
$pattern = '/^' . str_replace('\.\*', '\..+', preg_quote($field, '/')) . '$/';
return (bool) preg_grep($pattern, array_keys($this->getErrors()));
return (bool) preg_grep(self::getRegex($field), array_keys($this->getErrors()));
}
/**
@ -831,10 +845,11 @@ class Validation implements ValidationInterface
$field = array_key_first($this->rules);
}
$errors = array_filter($this->getErrors(), static fn ($key) => preg_match(
'/^' . str_replace(['\.\*', '\*\.'], ['\..+', '.+\.'], preg_quote($field, '/')) . '$/',
$key
), ARRAY_FILTER_USE_KEY);
$errors = array_filter(
$this->getErrors(),
static fn ($key) => preg_match(self::getRegex($field), $key),
ARRAY_FILTER_USE_KEY
);
return $errors === [] ? '' : implode("\n", $errors);
}

View File

@ -1206,9 +1206,9 @@ class ValidationTest extends CIUnitTestCase
$request = new IncomingRequest($config, new URI(), 'php://input', new UserAgent());
$this->validation->setRules([
'id_user.*' => 'numeric',
'name_user.*' => 'alpha',
'contacts.*.name' => 'required',
'id_user.*' => 'numeric',
'name_user.*' => 'alpha',
'contacts.friends.*.name' => 'required',
]);
$this->validation->withRequest($request->withMethod('post'))->run();
@ -1216,7 +1216,7 @@ class ValidationTest extends CIUnitTestCase
'id_user.0' => 'The id_user.* field must contain only numbers.',
'name_user.0' => 'The name_user.* field may only contain alphabetical characters.',
'name_user.2' => 'The name_user.* field may only contain alphabetical characters.',
'contacts.friends.0.name' => 'The contacts.*.name field is required.',
'contacts.friends.0.name' => 'The contacts.friends.*.name field is required.',
], $this->validation->getErrors());
$this->assertSame(
@ -1225,8 +1225,8 @@ class ValidationTest extends CIUnitTestCase
$this->validation->getError('name_user.*')
);
$this->assertSame(
'The contacts.*.name field is required.',
$this->validation->getError('contacts.*.name')
'The contacts.friends.*.name field is required.',
$this->validation->getError('contacts.friends.*.name')
);
}
@ -1323,17 +1323,17 @@ class ValidationTest extends CIUnitTestCase
}
/**
* @dataProvider provideDotNotationOnIfExistRule
* @dataProvider provideIfExistRuleWithAsterisk
*
* @see https://github.com/codeigniter4/CodeIgniter4/issues/4521
*/
public function testDotNotationOnIfExistRule(bool $expected, array $rules, array $data): void
public function testIfExistRuleWithAsterisk(bool $expected, array $rules, array $data): void
{
$actual = $this->validation->setRules($rules)->run($data);
$this->assertSame($expected, $actual);
}
public static function provideDotNotationOnIfExistRule(): iterable
public static function provideIfExistRuleWithAsterisk(): iterable
{
yield 'dot-on-end-fail' => [
false,
@ -1708,7 +1708,7 @@ class ValidationTest extends CIUnitTestCase
/**
* @see https://github.com/codeigniter4/CodeIgniter4/issues/5942
*/
public function testRequireWithoutWithWildCard(): void
public function testRequireWithoutWithAsterisk(): void
{
$data = [
'a' => [
@ -1726,4 +1726,50 @@ class ValidationTest extends CIUnitTestCase
$this->validation->getError('a.1.c')
);
}
/**
* @see https://github.com/codeigniter4/CodeIgniter4/issues/8128
*/
public function testRuleWithAsteriskToMultiDimensionalArray(): void
{
$data = [
'contacts' => [
'name' => 'Joe Smith',
'just' => [
'friends' => [
[
'name' => 'Fred Flinstone',
],
[
'name' => 'Wilma',
],
],
],
],
];
$this->validation->setRules(
['contacts.just.friends.*.name' => 'required|max_length[1]']
);
$this->assertFalse($this->validation->run($data));
$this->assertSame(
[
'contacts.just.friends.0.name' => 'The contacts.just.friends.*.name field cannot exceed 1 characters in length.',
'contacts.just.friends.1.name' => 'The contacts.just.friends.*.name field cannot exceed 1 characters in length.',
],
$this->validation->getErrors()
);
$this->validation->reset();
$this->validation->setRules(
['contacts.*.name' => 'required|max_length[1]']
);
$this->assertFalse($this->validation->run($data));
$this->assertSame(
// The data for `contacts.*.name` does not exist. So it is interpreted
// as `null`, and this error message returns.
['contacts.*.name' => 'The contacts.*.name field is required.'],
$this->validation->getErrors()
);
}
}

View File

@ -14,6 +14,13 @@ Release Date: Unreleased
BREAKING
********
Validation with Dot Array Syntax
================================
A validation rule with the wildcard ``*`` now validates only data in correct
dimensions as "dot array syntax".
See :ref:`Upgrading <upgrade-444-validation-with-dot-array-syntax>` for details.
***************
Message Changes
***************

View File

@ -20,6 +20,25 @@ Mandatory File Changes
Breaking Changes
****************
.. _upgrade-444-validation-with-dot-array-syntax:
Validation with Dot Array Syntax
================================
If you are using :ref:`dot array syntax <validation-dot-array-syntax>` in validation
rules, a bug where ``*`` would validate data in incorrect dimensions has been fixed.
In previous versions, the rule key ``contacts.*.name`` captured data with any
level like ``contacts.*.name``, ``contacts.*.*.name``, ``contacts.*.*.*.name``,
etc., incorrectly.
The following code explains details:
.. literalinclude:: upgrade_444/001.php
:lines: 2-
If you have code that depends on the bug, fix the the rule key.
*********************
Breaking Enhancements
*********************

View File

@ -0,0 +1,38 @@
<?php
use Config\Services;
$validation = Services::validation();
$data = [
'contacts' => [
'name' => 'Joe Smith',
'just' => [
'friends' => [
['name' => 'SATO Taro'],
['name' => 'Li Ming'],
['name' => 'Heinz Müller'],
],
],
],
];
$validation->setRules(
['contacts.*.name' => 'required|max_length[8]']
);
$validation->run($data); // false
d($validation->getErrors());
/*
Before: Captured `contacts.*.*.*.name` incorrectly.
[
contacts.just.friends.0.name => "The contacts.*.name field cannot exceed 8 characters in length.",
contacts.just.friends.2.name => "The contacts.*.name field cannot exceed 8 characters in length.",
]
After: Captures no data for `contacts.*.name`.
[
contacts.*.name => string (38) "The contacts.*.name field is required.",
]
*/

View File

@ -325,6 +325,8 @@ To give a labeled error message you can set up as:
.. note:: ``setRules()`` will overwrite any rules that were set previously. To add more than one
rule to an existing set of rules, use ``setRule()`` multiple times.
.. _validation-dot-array-syntax:
Setting Rules for Array Data
============================
@ -339,6 +341,10 @@ You can use the ``*`` wildcard symbol to match any one level of the array:
.. literalinclude:: validation/010.php
:lines: 2-
.. note:: Prior to v4.4.4, due to a bug, the wildcard ``*`` validated data in incorrect
dimensions. See :ref:`Upgrading <upgrade-444-validation-with-dot-array-syntax>`
for details.
"dot array syntax" can also be useful when you have single dimension array data.
For example, data returned by multi select dropdown:
@ -602,7 +608,7 @@ If you need to retrieve all error messages for failed fields, you can use the ``
If no errors exist, an empty array will be returned.
When using a wildcard, the error will point to a specific field, replacing the asterisk with the appropriate key/keys::
When using a wildcard (``*``), the error will point to a specific field, replacing the asterisk with the appropriate key/keys::
// for data
'contacts' => [
@ -617,10 +623,10 @@ When using a wildcard, the error will point to a specific field, replacing the a
]
// rule
'contacts.*.name' => 'required'
'contacts.friends.*.name' => 'required'
// error will be
'contacts.friends.1.name' => 'The contacts.*.name field is required.'
'contacts.friends.1.name' => 'The contacts.friends.*.name field is required.'
Getting a Single Error
======================
@ -864,7 +870,8 @@ alpha_numeric_punct No Fails if field contains anything other than
alphanumeric, space, or this limited set of
punctuation characters: ``~`` (tilde),
``!`` (exclamation), ``#`` (number),
``$`` (dollar), ``% (percent), & (ampersand),
``$`` (dollar), ``%`` (percent),
``&`` (ampersand),
``*`` (asterisk), ``-`` (dash),
``_`` (underscore), ``+`` (plus),
``=`` (equals), ``|`` (vertical bar),

View File

@ -4,7 +4,7 @@
* The data to test:
* [
* 'contacts' => [
* 'name' => 'Joe Smith',
* 'name' => 'Joe Smith',
* 'friends' => [
* [
* 'name' => 'Fred Flinstone',
@ -21,8 +21,3 @@
$validation->setRules([
'contacts.name' => 'required|max_length[60]',
]);
// Fred Flintsone & Wilma
$validation->setRules([
'contacts.friends.name' => 'required|max_length[60]',
]);

View File

@ -2,5 +2,5 @@
// Fred Flintsone & Wilma
$validation->setRules([
'contacts.*.name' => 'required|max_length[60]',
'contacts.friends.*.name' => 'required|max_length[60]',
]);