Skip to content

Commit

Permalink
Add type to error messages related with incorrect input (#736)
Browse files Browse the repository at this point in the history
* Revert "Revert "Change type of `$escape` argument in `Error::getValuePath()` from `bool|string|null` to `string|null`""

This reverts commit c5a2b49.

* Add type to error messages where possible

* Apply fixes from StyleCI

* Fix remaining tests

* Apply fixes from StyleCI

* Update changelog [skip ci]

* Fix message [skip ci]

---------

Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
arogachev and StyleCIBot authored Jul 31, 2024
1 parent d7896c3 commit c8e7ad1
Show file tree
Hide file tree
Showing 46 changed files with 457 additions and 593 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## 2.0.0 under development

- Enh #492: Add type to error messages related with incorrect input (@arogachev)
- Enh #735: Make `Json::$message` a bit more clear (@arogachev)
- Bug #736: Fix wrong value for `type` parameter for `Each::$incorrectInputKeyMessage` (@arogachev)
- New #734: Add `InEnum` rule (@samdark)
- New #630, #718: Include attribute name in error messages when it's present (@dood-, @arogachev)
- New #646, #653: Add `DateTime` rule (@pamparam83)
Expand Down
41 changes: 23 additions & 18 deletions messages/ru/yii-validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,16 @@
/** @see BooleanValue */
'{Property} must be either "{true}" or "{false}".' => '{Property} должно быть «{true}» или «{false}».',
/** @see Count */
'{Property} must be an array or implement \Countable interface.' => '{Property} должно быть массивом или объектом, реализующим интерфейс \Countable.',
'{Property} must be an array or implement \Countable interface. {type} given.' =>
'{Property} должно быть массивом или объектом, реализующим интерфейс \Countable. Передан {type}.',
'{Property} must contain at least {min, number} {min, plural, one{item} other{items}}.' => '{Property} должно содержать как минимум {min, number} {min, plural, one{элемент} few{элемента} many{элементов} other{элементов}}.',
'{Property} must contain at most {max, number} {max, plural, one{item} other{items}}.' => '{Property} должно содержать не более {max, number} {max, plural, one{элемента} few{элементов} many{элементов} other{элементов}}.',
'{Property} must contain exactly {exactly, number} {exactly, plural, one{item} other{items}}.' => '{Property} должно содержать ровно {exactly, number} {exactly, plural, one{элемент} few{элемента} many{элементов} other{элементов}}.',
/** @see Each */
'{Property} must be array or iterable.' => '{Property} должно быть массивом или иметь псевдотип iterable.',
'Every iterable key of {property} must have an integer or a string type.' =>
'Ключ {property} должен иметь тип integer или string.',
'{Property} must be array or iterable. {type} given.' =>
'{Property} должно быть массивом или иметь псевдотип iterable. Передан {type}',
'Every iterable key of {property} must have an integer or a string type. {type} given.' =>
'Ключ {property} должен иметь тип integer или string. Передан {type}.',
/** @see Email */
'{Property} is not a valid email address.' => '{Property} не является правильным адресом электронной почты.',
/** @see In */
Expand All @@ -68,14 +70,16 @@
*/
'{Property} must be an integer.' => '{Property} должно быть целым числом.',
/** @see Json */
'{Property} is not JSON.' => '{Property} не является строкой JSON.',
'{Property} is not a valid JSON.' => '{Property} не является валидной строкой JSON.',
/** @see Length */
'{Property} must contain at least {min, number} {min, plural, one{character} other{characters}}.' => '{Property} должно содержать как минимум {min, number} {min, plural, one{символ} few{символа} many{символов} other{символов}}.',
'{Property} must contain at most {max, number} {max, plural, one{character} other{characters}}.' => '{Property} должно содержать не более {max, number} {max, plural, one{символа} few{символов} many{символов} other{символов}}.',
'{Property} must contain exactly {exactly, number} {exactly, plural, one{character} other{characters}}.' => '{Property} должно содержать ровно {exactly, number} {exactly, plural, one{символ} few{символа} many{символов} other{символов}}.',
/** @see Nested */
'Nested rule without rules requires {property} to be an object.' => 'При правиле Nested без указания правил {property} должно быть объектом,',
'An object data set data for {property} can only have an array type.' => 'Данные в объекте для {property} должны быть массивом.',
'Nested rule without rules requires {property} to be an object. {type} given.' =>
'При правиле Nested без указания правил {property} должно быть объектом. Передан {type}.',
'An object data set data for {property} can only have an array type. {type} given.' =>
'Данные в объекте для {property} должны быть массивом. Передан {type}.',
'Property "{path}" is not found in {property}.' => 'Свойство «{path}» не найдено в {property}.',
/** @see Number */
'{Property} must be a number.' => '{Property} должно быть числом.',
Expand All @@ -88,7 +92,7 @@
'{Property} cannot be blank.' => '{Property} не может быть пустым.',
'{Property} not passed.' => '{Property} не передано.',
/** @see Subset */
'{Property} must be iterable.' => '{Property} должно быть итерируемым.',
'{Property} must be iterable. {type} given.' => '{Property} должно быть итерируемым. Передан {type}.',
'{Property} is not a subset of acceptable values.' => '{Property} не является подмножеством допустимых значений.',
/** @see TrueValue */
'{Property} must be "{true}".' => '{Property} должно быть «{true}».',
Expand All @@ -102,7 +106,8 @@
* @see Nested
* @see OneOf
*/
'{Property} must be an array or an object.' => '{Property} должно быть массивом или объектом.',
'{Property} must be an array or an object. {type} given.' => '{Property} должно быть массивом или объектом. ' .
'Передан {type}.',
/**
* @see BooleanValue
* @see TrueValue
Expand All @@ -118,10 +123,10 @@
* @see LessThanOrEqual
* @see NotEqual
*/
'The allowed types for {property} are integer, float, string, boolean, null and object implementing \Stringable or \DateTimeInterface.' =>
'Разрешённые типы для {property}: integer, float, string, boolean, null и объект, реализующий интерфейс \Stringable или \DateTimeInterface.',
'{Property} returned from a custom data set must have one of the following types: integer, float, string, boolean, null or an object implementing \Stringable interface or \DateTimeInterface.' =>
'{Property}, получаемое из пользовательского набора данных, должно иметь один из следующих типов: integer, float, string, bool, null или объект, реализующий интерфейс \Stringable или \DateTimeInterface.',
'The allowed types for {property} are integer, float, string, boolean, null and object implementing \Stringable or \DateTimeInterface. {type} given.' =>
'Разрешённые типы для {property}: integer, float, string, boolean, null и объект, реализующий интерфейс \Stringable или \DateTimeInterface. Передан {type}.',
'{Property} returned from a custom data set must have one of the following types: integer, float, string, boolean, null or an object implementing \Stringable interface or \DateTimeInterface. {type} given.' =>
'{Property}, получаемое из пользовательского набора данных, должно иметь один из следующих типов: integer, float, string, bool, null или объект, реализующий интерфейс \Stringable или \DateTimeInterface. Передан {type}.',
'{Property} must be equal to "{targetValueOrProperty}".' => '{Property} должно быть равно «{targetValueOrProperty}».',
'{Property} must be strictly equal to "{targetValueOrProperty}".' => '{Property} должно быть строго равно «{targetValueOrProperty}».',
'{Property} must not be equal to "{targetValueOrProperty}".' => '{Property} не должно быть равно «{targetValueOrProperty}».',
Expand All @@ -139,12 +144,12 @@
* @see StringType
* @see Url
*/
'{Property} must be a string.' => '{Property} должно быть строкой.',
'{Property} must be a string. {type} given.' => '{Property} должно быть строкой. Передан {type}.',
/**
* @see Number
* @see Integer
*/
'The allowed types for {property} are integer, float and string.' => 'Разрешённые типы: integer, float и string.',
'The allowed types for {property} are integer, float and string. {type} given.' => 'Разрешённые типы: integer, float и string. Передан {type}.',
'{Property} must be no less than {min}.' => '{Property} должно быть не меньше {min}.',
'{Property} must be no greater than {max}.' => '{Property} должно быть не больше {max}.',

Expand All @@ -160,16 +165,16 @@
* @see \Yiisoft\Validator\Rule\Date\Date
* @see \Yiisoft\Validator\Rule\Date\DateTime
*/
'{Property} must be a date' => '{Property} должно быть датой.',
'{Property} must be a date.' => '{Property} должно быть датой.',

/**
* @see \Yiisoft\Validator\Rule\Date\Time
*/
'{Property} must be a time.' => '{Property} должно быть временем.',

/** @see UniqueIterable */
'The allowed types for iterable\'s item values of {property} are integer, float, string, boolean, null and object implementing \Stringable or \DateTimeInterface.' =>
'Разрешённые типы для значений элементов списка {property}: integer, float, string, boolean, null и объект, реализующий интерфейс \Stringable или \DateTimeInterface.',
'The allowed types for iterable\'s item values of {property} are integer, float, string, boolean, null and object implementing \Stringable or \DateTimeInterface. {type} given.' =>
'Разрешённые типы для значений элементов списка {property}: integer, float, string, boolean, null и объект, реализующий интерфейс \Stringable или \DateTimeInterface. Передан {type}.',
'All iterable items of {property} must have the same type.' =>
'Все элементы списка {property} должны иметь одинаковый тип.',
'Every iterable\'s item must be unique.' => 'Каждый элемент списка {property} должен быть уникален.',
Expand Down
2 changes: 1 addition & 1 deletion src/Rule/AbstractCompare.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ abstract class AbstractCompare implements
* A default for {@see $incorrectInputMessage}.
*/
protected const DEFAULT_INCORRECT_INPUT_MESSAGE = 'The allowed types for {property} are integer, float, string, ' .
'boolean, null and object implementing \Stringable interface or \DateTimeInterface.';
'boolean, null and object implementing \Stringable interface or \DateTimeInterface. {type} given.';
/**
* A default for {@see $incorrectDataSetTypeMessage}.
*/
Expand Down
3 changes: 2 additions & 1 deletion src/Rule/AbstractNumber.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ abstract class AbstractNumber implements
/**
* A default for {@see $incorrectInputMessage}.
*/
protected const DEFAULT_INCORRECT_INPUT_MESSAGE = 'The allowed types for {property} are integer, float and string.';
protected const DEFAULT_INCORRECT_INPUT_MESSAGE = 'The allowed types for {property} are integer, float and ' .
'string. {type} given.';
/**
* A default for {@see $lessThanMinMessage}.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/Rule/AtLeast.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ final class AtLeast implements DumpedRuleInterface, SkipOnErrorInterface, WhenIn
public function __construct(
private array $properties,
private int $min = 1,
private string $incorrectInputMessage = '{Property} must be an array or an object.',
private string $incorrectInputMessage = '{Property} must be an array or an object. {type} given.',
private string $message = 'At least {min, number} {min, plural, one{property} other{properties}} from this ' .
'list must be filled for {property}: {properties}.',
bool|callable|null $skipOnEmpty = null,
Expand Down
3 changes: 2 additions & 1 deletion src/Rule/Count.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public function __construct(
int|null $exactly = null,
int|null $min = null,
int|null $max = null,
private string $incorrectInputMessage = '{Property} must be an array or implement \Countable interface.',
private string $incorrectInputMessage = '{Property} must be an array or implement \Countable interface. ' .
'{type} given.',
string $lessThanMinMessage = '{Property} must contain at least {min, number} {min, plural, one{item} ' .
'other{items}}.',
string $greaterThanMaxMessage = '{Property} must contain at most {max, number} {max, plural, one{item} ' .
Expand Down
4 changes: 2 additions & 2 deletions src/Rule/Each.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ final class Each implements
*/
public function __construct(
callable|iterable|object|string $rules = [],
private string $incorrectInputMessage = '{Property} must be array or iterable.',
private string $incorrectInputMessage = '{Property} must be array or iterable. {type} given.',
private string $incorrectInputKeyMessage = 'Every iterable key of {property} must have an integer or a ' .
'string type.',
'string type. {type} given.',
bool|callable|null $skipOnEmpty = null,
private bool $skipOnError = false,
private Closure|null $when = null,
Expand Down
2 changes: 1 addition & 1 deletion src/Rule/EachHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function validate(mixed $value, RuleInterface $rule, ValidationContext $c
return (new Result())->addError($rule->getIncorrectInputKeyMessage(), [
'property' => $context->getTranslatedProperty(),
'Property' => $context->getCapitalizedTranslatedProperty(),
'type' => get_debug_type($value),
'type' => get_debug_type($index),
]);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Rule/Email.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public function __construct(
private bool $allowName = false,
private bool $checkDns = false,
private bool $enableIdn = false,
private string $incorrectInputMessage = '{Property} must be a string.',
private string $incorrectInputMessage = '{Property} must be a string. {type} given.',
private string $message = '{Property} is not a valid email address.',
bool|callable|null $skipOnEmpty = null,
private bool $skipOnError = false,
Expand Down
2 changes: 2 additions & 0 deletions src/Rule/InEnumHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Yiisoft\Validator\RuleHandlerInterface;
use Yiisoft\Validator\ValidationContext;

use function in_array;

/**
* Validates that the value is one of the values of a specified enum.
*
Expand Down
2 changes: 1 addition & 1 deletion src/Rule/Ip.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public function __construct(
private bool $allowSubnet = false,
private bool $requireSubnet = false,
private bool $allowNegation = false,
private string $incorrectInputMessage = '{Property} must be a string.',
private string $incorrectInputMessage = '{Property} must be a string. {type} given.',
private string $message = '{Property} must be a valid IP address.',
private string $ipv4NotAllowedMessage = '{Property} must not be an IPv4 address.',
private string $ipv6NotAllowedMessage = '{Property} must not be an IPv6 address.',
Expand Down
4 changes: 2 additions & 2 deletions src/Rule/Json.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ final class Json implements DumpedRuleInterface, SkipOnErrorInterface, WhenInter
* @psalm-param WhenType $when
*/
public function __construct(
private string $incorrectInputMessage = '{Property} must be a string.',
private string $message = '{Property} is not JSON.',
private string $incorrectInputMessage = '{Property} must be a string. {type} given.',
private string $message = '{Property} is not a valid JSON.',
bool|callable|null $skipOnEmpty = null,
private bool $skipOnError = false,
private Closure|null $when = null,
Expand Down
2 changes: 1 addition & 1 deletion src/Rule/Length.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public function __construct(
int|null $exactly = null,
int|null $min = null,
int|null $max = null,
private string $incorrectInputMessage = '{Property} must be a string.',
private string $incorrectInputMessage = '{Property} must be a string. {type} given.',
string $lessThanMinMessage = '{Property} must contain at least {min, number} {min, plural, one{character} ' .
'other{characters}}.',
string $greaterThanMaxMessage = '{Property} must contain at most {max, number} {max, plural, one{character} ' .
Expand Down
8 changes: 5 additions & 3 deletions src/Rule/Nested.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,11 @@ public function __construct(
private int $rulesSourceClassPropertyVisibility = ReflectionProperty::IS_PRIVATE
| ReflectionProperty::IS_PROTECTED
| ReflectionProperty::IS_PUBLIC,
private string $noRulesWithNoObjectMessage = 'Nested rule without rules requires {property} to be an object.',
private string $incorrectDataSetTypeMessage = 'An object data set data for {property} can only have an array type.',
private string $incorrectInputMessage = '{Property} must be an array or an object.',
private string $noRulesWithNoObjectMessage = 'Nested rule without rules requires {property} to be an object. ' .
'{type} given.',
private string $incorrectDataSetTypeMessage = 'An object data set data for {property} can only have an array ' .
'type. {type} given.',
private string $incorrectInputMessage = '{Property} must be an array or an object. {type} given.',
private bool $requirePropertyPath = false,
private string $noPropertyPathMessage = 'Property "{path}" is not found in {property}.',
private bool $handleEachShortcut = true,
Expand Down
2 changes: 1 addition & 1 deletion src/Rule/Number.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ final class Number extends AbstractNumber
public function __construct(
float|int|null $min = null,
float|int|null $max = null,
string $incorrectInputMessage = 'The allowed types for {property} are integer, float and string.',
string $incorrectInputMessage = 'The allowed types for {property} are integer, float and string. {type} given.',
string $notNumberMessage = '{Property} must be a number.',
string $lessThanMinMessage = '{Property} must be no less than {min}.',
string $greaterThanMaxMessage = '{Property} must be no greater than {max}.',
Expand Down
2 changes: 1 addition & 1 deletion src/Rule/OneOf.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ final class OneOf implements DumpedRuleInterface, SkipOnErrorInterface, WhenInte
*/
public function __construct(
private array $properties,
private string $incorrectInputMessage = '{Property} must be an array or an object.',
private string $incorrectInputMessage = '{Property} must be an array or an object. {type} given.',
private string $message = 'Exactly 1 property from this list must be filled for {property}: {properties}.',
bool|callable|null $skipOnEmpty = null,
private bool $skipOnError = false,
Expand Down
2 changes: 1 addition & 1 deletion src/Rule/Regex.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function __construct(
#[Language('RegExp')]
string $pattern,
private bool $not = false,
private string $incorrectInputMessage = '{Property} must be a string.',
private string $incorrectInputMessage = '{Property} must be a string. {type} given.',
private string $message = '{Property} is invalid.',
bool|callable|null $skipOnEmpty = null,
private bool $skipOnError = false,
Expand Down
Loading

0 comments on commit c8e7ad1

Please sign in to comment.