diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml
index adacd735a..bd79331da 100644
--- a/.github/workflows/rector.yml
+++ b/.github/workflows/rector.yml
@@ -14,8 +14,10 @@ name: rector
jobs:
rector:
uses: yiisoft/actions/.github/workflows/rector.yml@master
+ secrets:
+ token: ${{ secrets.YIISOFT_GITHUB_TOKEN }}
with:
os: >-
['ubuntu-latest']
php: >-
- ['8.0']
+ ['8.2']
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 446ebd6c0..09ec86a77 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@
- Chg #624: Fix meaning of error message in `OneOf` rule (@arogachev)
- Chg #625: Improve meaning and use pluralization in error message for `OneOf` and `AtLeast` rules (@arogachev)
- Chg #626: Disallow `$min` greater than amount of `$attributes` in `AtLeast` configuration (@arogachev)
+- Bug #632: Fix property name usage in error messages of rules in `Nested` rule (@vjik)
## 1.1.0 April 06, 2023
diff --git a/psalm.xml b/psalm.xml
index f4cecedef..d091d59c2 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -9,5 +9,11 @@
>
+
+
+
+
+
+
diff --git a/src/Rule/EmailHandler.php b/src/Rule/EmailHandler.php
index d0c3daa84..b1b88f34e 100644
--- a/src/Rule/EmailHandler.php
+++ b/src/Rule/EmailHandler.php
@@ -44,7 +44,7 @@ public function validate(mixed $value, object $rule, ValidationContext $context)
if ($rule->isIdnEnabled()) {
$matches['local'] = idn_to_ascii($matches['local']);
$matches['domain'] = idn_to_ascii($matches['domain']);
- $value = implode([
+ $value = implode('', [
$matches['name'],
$matches['open'],
$matches['local'],
diff --git a/src/Rule/NestedHandler.php b/src/Rule/NestedHandler.php
index cbb33fc46..2a2e263f2 100644
--- a/src/Rule/NestedHandler.php
+++ b/src/Rule/NestedHandler.php
@@ -63,12 +63,9 @@ public function validate(mixed $value, object $rule, ValidationContext $context)
foreach ($rule->getRules() as $valuePath => $rules) {
if ($rule->isPropertyPathRequired() && !ArrayHelper::pathExists($data, $valuePath)) {
- if (is_int($valuePath)) {
- $valuePathList = [$valuePath];
- } else {
- /** @var list $valuePathList */
- $valuePathList = StringHelper::parsePath($valuePath);
- }
+ $valuePathList = is_int($valuePath)
+ ? [$valuePath]
+ : StringHelper::parsePath($valuePath);
$compoundResult->addError(
$rule->getNoPropertyPathMessage(),
@@ -82,25 +79,24 @@ public function validate(mixed $value, object $rule, ValidationContext $context)
continue;
}
- /** @var mixed $validatedValue */
$validatedValue = ArrayHelper::getValueByPath($data, $valuePath);
- $itemResult = $context->validate($validatedValue, $rules);
+ if (is_int($valuePath)) {
+ $itemResult = $context->validate($validatedValue, $rules);
+ } else {
+ $valuePathList = StringHelper::parsePath($valuePath);
+ $attribute = (string) end($valuePathList);
+ $itemResult = $context->validate([$attribute => $validatedValue], [$attribute => $rules]);
+ }
+
if ($itemResult->isValid()) {
continue;
}
foreach ($itemResult->getErrors() as $error) {
- if (is_int($valuePath)) {
- $valuePathList = [$valuePath];
- } else {
- /** @var list $valuePathList */
- $valuePathList = StringHelper::parsePath($valuePath);
- }
-
- if (!empty($valuePathList)) {
- array_push($valuePathList, ...$error->getValuePath());
- }
+ $valuePathList = is_int($valuePath)
+ ? [$valuePath, ...$error->getValuePath()]
+ : [...StringHelper::parsePath($valuePath), ...array_slice($error->getValuePath(), 1)];
$compoundResult->addError($error->getMessage(), $error->getParameters(), $valuePathList);
}
diff --git a/tests/Rule/NestedTest.php b/tests/Rule/NestedTest.php
index 86c10aed7..5d80aa154 100644
--- a/tests/Rule/NestedTest.php
+++ b/tests/Rule/NestedTest.php
@@ -1263,6 +1263,21 @@ public function hasAttribute(string $attribute): bool
'level1.level2.level3.name' => ['This value must contain at least 5 characters.'],
],
],
+ 'error messages with attributes in nested structure' => [
+ [
+ 'user' => [
+ 'name' => '',
+ ],
+ ],
+ new Nested([
+ 'user' => [
+ 'name' => new Required(message: '{attribute} is required.'),
+ ],
+ ]),
+ [
+ 'user.name' => ['name is required.'],
+ ],
+ ],
];
}