yiisoft /
validator
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace Yiisoft\Validator\Rule; |
||
| 6 | |||
| 7 | use Attribute; |
||
| 8 | use Closure; |
||
| 9 | use InvalidArgumentException; |
||
| 10 | use Yiisoft\Validator\Rule\Trait\SkipOnEmptyTrait; |
||
| 11 | use Yiisoft\Validator\Rule\Trait\SkipOnErrorTrait; |
||
| 12 | use Yiisoft\Validator\Rule\Trait\WhenTrait; |
||
| 13 | use Yiisoft\Validator\DumpedRuleInterface; |
||
| 14 | use Yiisoft\Validator\SkipOnEmptyInterface; |
||
| 15 | use Yiisoft\Validator\SkipOnErrorInterface; |
||
| 16 | use Yiisoft\Validator\WhenInterface; |
||
| 17 | |||
| 18 | use function count; |
||
|
0 ignored issues
–
show
|
|||
| 19 | |||
| 20 | /** |
||
| 21 | * Defines validation options to check that a minimum number of specified attributes are filled. |
||
| 22 | * |
||
| 23 | * Both arrays and objects with public properties are supported as validated values. |
||
| 24 | * |
||
| 25 | * @see AtLeastHandler |
||
| 26 | * |
||
| 27 | * @psalm-import-type WhenType from WhenInterface |
||
| 28 | 3 | */ |
|
| 29 | #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] |
||
| 30 | final class AtLeast implements DumpedRuleInterface, SkipOnErrorInterface, WhenInterface, SkipOnEmptyInterface |
||
| 31 | { |
||
| 32 | use SkipOnEmptyTrait; |
||
| 33 | use SkipOnErrorTrait; |
||
| 34 | use WhenTrait; |
||
| 35 | |||
| 36 | /** |
||
| 37 | * @param string[] $attributes The list of required attributes that will be checked. |
||
| 38 | * @param int $min The minimum required quantity of filled attributes to pass the validation. Defaults to 1. |
||
| 39 | * @param string $incorrectInputMessage A message used when the input is incorrect. |
||
| 40 | * |
||
| 41 | * You may use the following placeholders in the message: |
||
| 42 | * |
||
| 43 | * - `{attribute}`: the translated label of the attribute being validated. |
||
| 44 | * - `{type}`: the type of the value being validated. |
||
| 45 | * @param string $message A message used when the value is not valid. |
||
| 46 | * |
||
| 47 | * You may use the following placeholders in the message: |
||
| 48 | * |
||
| 49 | * - `{attribute}`: the translated label of the attribute being validated. |
||
| 50 | * - `{min}`: the minimum number of attribute values that was not met. |
||
| 51 | * @param bool|callable|null $skipOnEmpty Whether to skip this rule if the value validated is empty. |
||
| 52 | * See {@see SkipOnEmptyInterface}. |
||
| 53 | * @param bool $skipOnError Whether to skip this rule if any of the previous rules gave an error. |
||
| 54 | 1 | * See {@see SkipOnErrorInterface}. |
|
| 55 | * @param Closure|null $when A callable to define a condition for applying the rule. |
||
| 56 | 1 | * See {@see WhenInterface}. |
|
| 57 | * |
||
| 58 | * @psalm-param WhenType $when |
||
| 59 | */ |
||
| 60 | public function __construct( |
||
| 61 | private array $attributes, |
||
| 62 | 15 | private int $min = 1, |
|
| 63 | private string $incorrectInputMessage = 'The value must be an array or an object.', |
||
| 64 | 15 | private string $message = 'At least {min, number} {min, plural, one{attribute} other{attributes}} from this ' . |
|
| 65 | 'list must be filled: {attributes}.', |
||
| 66 | private mixed $skipOnEmpty = null, |
||
| 67 | 15 | private bool $skipOnError = false, |
|
| 68 | private Closure|null $when = null |
||
| 69 | 15 | ) { |
|
| 70 | if ($min > count($this->attributes)) { |
||
| 71 | throw new InvalidArgumentException('$min must be no greater than amount of $attributes.'); |
||
| 72 | 4 | } |
|
| 73 | } |
||
| 74 | 4 | ||
| 75 | public function getName(): string |
||
| 76 | { |
||
| 77 | 7 | return self::class; |
|
| 78 | } |
||
| 79 | 7 | ||
| 80 | /** |
||
| 81 | * Get the list of required attributes that will be checked. |
||
| 82 | 2 | * |
|
| 83 | * @return string[] The list of attributes. |
||
| 84 | * |
||
| 85 | 2 | * @see $attributes |
|
| 86 | 2 | */ |
|
| 87 | public function getAttributes(): array |
||
| 88 | 2 | { |
|
| 89 | return $this->attributes; |
||
| 90 | } |
||
| 91 | |||
| 92 | 2 | /** |
|
| 93 | 2 | * Get the minimum required quantity of filled attributes to pass the validation. |
|
| 94 | * |
||
| 95 | 2 | * @return int Minimum require quantity. |
|
| 96 | 2 | * |
|
| 97 | * @see $min |
||
| 98 | */ |
||
| 99 | public function getMin(): int |
||
| 100 | 19 | { |
|
| 101 | return $this->min; |
||
| 102 | 19 | } |
|
| 103 | |||
| 104 | /** |
||
| 105 | * Get the message used when the input is incorrect. |
||
| 106 | * |
||
| 107 | * @return string Error message. |
||
| 108 | * |
||
| 109 | * @see $incorrectInputMessage |
||
| 110 | */ |
||
| 111 | public function getIncorrectInputMessage(): string |
||
| 112 | { |
||
| 113 | return $this->incorrectInputMessage; |
||
| 114 | } |
||
| 115 | |||
| 116 | /** |
||
| 117 | * Get the message used when the value is not valid. |
||
| 118 | * |
||
| 119 | * @return string Error message. |
||
| 120 | * |
||
| 121 | * @see $message |
||
| 122 | */ |
||
| 123 | public function getMessage(): string |
||
| 124 | { |
||
| 125 | return $this->message; |
||
| 126 | } |
||
| 127 | |||
| 128 | public function getOptions(): array |
||
| 129 | { |
||
| 130 | return [ |
||
| 131 | 'attributes' => $this->attributes, |
||
| 132 | 'min' => $this->min, |
||
| 133 | 'incorrectInputMessage' => [ |
||
| 134 | 'template' => $this->incorrectInputMessage, |
||
| 135 | 'parameters' => [], |
||
| 136 | ], |
||
| 137 | 'message' => [ |
||
| 138 | 'template' => $this->message, |
||
| 139 | 'parameters' => ['min' => $this->min], |
||
| 140 | ], |
||
| 141 | 'skipOnEmpty' => $this->getSkipOnEmptyOption(), |
||
| 142 | 'skipOnError' => $this->skipOnError, |
||
| 143 | ]; |
||
| 144 | } |
||
| 145 | |||
| 146 | public function getHandler(): string |
||
| 147 | { |
||
| 148 | return AtLeastHandler::class; |
||
| 149 | } |
||
| 150 | } |
||
| 151 |
Let?s assume that you have a directory layout like this:
. |-- OtherDir | |-- Bar.php | `-- Foo.php `-- SomeDir `-- Foo.phpand let?s assume the following content of
Bar.php:If both files
OtherDir/Foo.phpandSomeDir/Foo.phpare loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.phpHowever, as
OtherDir/Foo.phpdoes not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: