From 06e547275360fae5fcd7033ffb17015e2609c164 Mon Sep 17 00:00:00 2001 From: Anton Date: Fri, 8 Apr 2022 00:20:28 +0300 Subject: [PATCH] Fix #19256: Pass missed `$view` to user's callback in `yii\validators\InlineValidator::clientValidateAttribute()` --- framework/CHANGELOG.md | 1 + framework/validators/InlineValidator.php | 34 ++++++++----------- .../models/FakedValidationModel.php | 2 +- tests/framework/validators/ValidatorTest.php | 9 ++--- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index e7b3f4a2c3..3b3aade3dc 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -6,6 +6,7 @@ Yii Framework 2 Change Log - Bug #19243: Handle `finfo_open` for tar.xz as `application/octet-stream` on PHP 8.1 (longthanhtran) - Bug #19235: Fix return type compatibility of `yii\web\SessionIterator` class methods for PHP 8.1 (virtual-designer) +- Bug #19256: Pass missed `$view` to user's callback in `yii\validators\InlineValidator::clientValidateAttribute()` (WinterSilence) - Enh #19270: Replace deprecated `scss` converter in `yii\web\AssetConverter::$commands` (WinterSilence) - Enh #19254: Support specifying custom characters for `yii.validation.trim()` and replace deprecated `jQuery.trim()` (WinterSilence) - Bug #19291: Reset errors and validators in `yii\base\Model::__clone()` (WinterSilence) diff --git a/framework/validators/InlineValidator.php b/framework/validators/InlineValidator.php index a8dcd0040d..8692482641 100644 --- a/framework/validators/InlineValidator.php +++ b/framework/validators/InlineValidator.php @@ -10,15 +10,6 @@ namespace yii\validators; /** * InlineValidator represents a validator which is defined as a method in the object being validated. * - * The validation method must have the following signature: - * - * ```php - * function foo($attribute, $params, $validator) - * ``` - * - * where `$attribute` refers to the name of the attribute being validated, while `$params` is an array representing the - * additional parameters supplied in the validation rule. Parameter `$validator` refers to the related - * [[InlineValidator]] object and is available since version 2.0.11. * * @author Qiang Xue * @since 2.0 @@ -26,16 +17,18 @@ namespace yii\validators; class InlineValidator extends Validator { /** - * @var string|\Closure an anonymous function or the name of a model class method that will be + * @var string|callable an anonymous function or the name of a model class method that will be * called to perform the actual validation. The signature of the method should be like the following: * * ```php - * function foo($attribute, $params, $validator) + * function (string $attribute, mixed $params, InlineValidator $validator, mixed $current): bool { + * } * ``` * - * - `$attribute` is the name of the attribute to be validated; - * - `$params` contains the value of [[params]] that you specify when declaring the inline validation rule; - * - `$validator` is a reference to related [[InlineValidator]] object. This parameter is available since version 2.0.11. + * - `$attribute` is the name of the attribute to be validated + * - `$params` contains the value of [[params]] that you specify when declaring the inline validation rule + * - `$validator` is a reference to related [[InlineValidator]] object. This parameter is available since version 2.0.11 + * - `$current` is the attribute value. This parameter is available since version 2.0.36 */ public $method; /** @@ -47,15 +40,16 @@ class InlineValidator extends Validator * The signature of the method should be like the following: * * ```php - * function foo($attribute, $params, $validator) + * function (string $attribute, mixed $params, InlineValidator $validator, mixed $current, View $view): string * { - * return "javascript"; + * // $view->registerJs('JS validation function'); + * // or \app\assets\ValidationAsset::register($view); + * return "calling JS validation function"; * } * ``` * - * where `$attribute` refers to the attribute name to be validated. - * - * Please refer to [[clientValidateAttribute()]] for details on how to return client validation code. + * Please refer to [[clientValidateAttribute()]] and [guide](guide:input-validation#client-side-validation) for details on how + * to return client validation code. */ public $clientValidate; /** @@ -100,7 +94,7 @@ class InlineValidator extends Validator if ($current === null) { $current = $model->$attribute; } - return $method($attribute, $this->params, $this, $current); + return $method($attribute, $this->params, $this, $current, $view); } return null; diff --git a/tests/data/validators/models/FakedValidationModel.php b/tests/data/validators/models/FakedValidationModel.php index bb74d969e4..e96efa958d 100644 --- a/tests/data/validators/models/FakedValidationModel.php +++ b/tests/data/validators/models/FakedValidationModel.php @@ -51,7 +51,7 @@ class FakedValidationModel extends Model return true; } - public function clientInlineVal($attribute, $params, $validator, $current) + public function clientInlineVal($attribute, $params, $validator, $current, $view = null) { return \func_get_args(); } diff --git a/tests/framework/validators/ValidatorTest.php b/tests/framework/validators/ValidatorTest.php index a7b22e5693..a37e6544ef 100644 --- a/tests/framework/validators/ValidatorTest.php +++ b/tests/framework/validators/ValidatorTest.php @@ -217,19 +217,20 @@ class ValidatorTest extends TestCase public function testClientValidateAttribute() { + $view = new \yii\base\View(); $val = new TestValidator(); $this->assertNull( - $val->clientValidateAttribute($this->getTestModel(), 'attr_runMe1', []) - ); //todo pass a view instead of array + $val->clientValidateAttribute($this->getTestModel(), 'attr_runMe1', $view) + ); // Access to validator in inline validation (https://github.com/yiisoft/yii2/issues/6242) $model = new FakedValidationModel(); $val = Validator::createValidator('inlineVal', $model, ['val_attr_a'], ['params' => ['foo' => 'bar']]); $val->clientValidate = 'clientInlineVal'; - $args = $val->clientValidateAttribute($model, 'val_attr_a', null); + $args = $val->clientValidateAttribute($model, 'val_attr_a', $view); - $this->assertCount(4, $args); + $this->assertCount(5, $args); $this->assertEquals('val_attr_a', $args[0]); $this->assertEquals(['foo' => 'bar'], $args[1]); $this->assertInstanceOf(InlineValidator::className(), $args[2]);