diff --git a/CHANGELOG-5.0.md b/CHANGELOG-5.0.md index 48447347bb..1857872c21 100644 --- a/CHANGELOG-5.0.md +++ b/CHANGELOG-5.0.md @@ -17,6 +17,7 @@ All notable changes are documented here. The format is based on [Keep a Changelo - Faster item storage, lookup, removal and JSON serialization in `Phalcon\Support\Collection`. [#17683](https://github.com/phalcon/cphalcon/issues/17683) - Faster route index build in `Phalcon\Mvc\Router` for routes with no host name. [#17693](https://github.com/phalcon/cphalcon/issues/17693) - Faster service registration in `Phalcon\Factory\AbstractFactory` and the factories that extend it. [#17696](https://github.com/phalcon/cphalcon/issues/17696) +- Faster construction of the validators in `Phalcon\Filter\Validation`. [#17697](https://github.com/phalcon/cphalcon/issues/17697) ### Added diff --git a/phalcon/Filter/Validation/AbstractValidator.zep b/phalcon/Filter/Validation/AbstractValidator.zep index 4de94ee493..93fe48722f 100644 --- a/phalcon/Filter/Validation/AbstractValidator.zep +++ b/phalcon/Filter/Validation/AbstractValidator.zep @@ -14,7 +14,6 @@ use Phalcon\Contracts\Filter\FilterTypes; use Phalcon\Filter\Validation; use Phalcon\Filter\Validation\Exceptions\FieldNotPrintable; use Phalcon\Messages\Message; -use Phalcon\Support\Helper\Arr\Whitelist; /** * This is a base class for validators @@ -60,10 +59,17 @@ abstract class AbstractValidator implements ValidatorInterface */ public function __construct(array options = []) { - var template, whitelist; + var key, value, + template = false; - let whitelist = new Whitelist(), - template = current(whitelist->__invoke(options, ["template", "message", 0])); + // Find the first "template", "message" or 0 key, in the order of the options + for key, value in options { + if key === "template" || key === "message" || key === 0 { + let template = options[key]; + + break; + } + } if typeof template == "array" { this->setTemplates(template); diff --git a/tests/unit/Filter/Validation/Validator/ConstructTest.php b/tests/unit/Filter/Validation/Validator/ConstructTest.php index 0fc1b85c4f..ee62ab1983 100755 --- a/tests/unit/Filter/Validation/Validator/ConstructTest.php +++ b/tests/unit/Filter/Validation/Validator/ConstructTest.php @@ -74,6 +74,55 @@ public static function getExamples(): array ]; } + public static function getTemplateCases(): array + { + $default = 'Field :field is required'; + + // options, expected options, expected template, template changed, expected templates + return [ + 'no options' => [[], [], $default, false, []], + 'other option' => [['allowEmpty' => true], ['allowEmpty' => true], $default, false, []], + 'template' => [ + ['template' => 'Tpl', 'allowEmpty' => true], + ['allowEmpty' => true, 'message' => 'Tpl'], + 'Tpl', + true, + [], + ], + 'integer key' => [ + ['Msg0', 'allowEmpty' => true], + ['allowEmpty' => true, 'message' => 'Msg0'], + 'Msg0', + true, + [], + ], + 'message first' => [['message' => 'Msg', 'template' => 'Tpl'], ['message' => 'Msg'], 'Msg', true, []], + 'template first' => [['template' => 'Tpl', 'message' => 'Msg'], ['message' => 'Tpl'], 'Tpl', true, []], + 'empty string first' => [ + ['template' => '', 'message' => 'Msg'], + ['template' => '', 'message' => 'Msg'], + '', + true, + [], + ], + 'null first' => [ + ['message' => null, 'template' => 'Tpl'], + ['message' => null, 'template' => 'Tpl'], + $default, + false, + [], + ], + 'array templates' => [ + ['message' => ['name' => 'Name msg']], + ['message' => ['name' => 'Name msg']], + $default, + false, + ['name' => 'Name msg'], + ], + 'other integer key' => [[1 => 'One'], [1 => 'One'], $default, false, []], + ]; + } + /** * @author Phalcon Team * @since 2018-11-13 @@ -120,6 +169,56 @@ public function testFilterValidationValidatorConstruct(): void $this->assertSame($expected, $actual); } + /** + * @author Phalcon Team + * @since 2026-10-27 + */ + #[DataProvider('getTemplateCases')] + public function testFilterValidationValidatorConstructTemplate( + array $options, + array $expectedOptions, + string $expectedTemplate, + bool $expectedChanged, + array $expectedTemplates + ): void { + $validator = new PresenceOf($options); + + $actual = $this->getProtectedProperty($validator, 'options'); + $this->assertSame($expectedOptions, $actual); + + $actual = $this->getProtectedProperty($validator, 'template'); + $this->assertSame($expectedTemplate, $actual); + + $actual = $this->getProtectedProperty($validator, 'templateChanged'); + $this->assertSame($expectedChanged, $actual); + + $actual = $validator->getTemplates(); + $this->assertSame($expectedTemplates, $actual); + } + + /** + * @author Phalcon Team + * @since 2026-10-27 + */ + public function testFilterValidationValidatorConstructTemplateReference(): void + { + $message = 'Msg'; + $validator = new PresenceOf(['message' => &$message]); + + $actual = $this->getProtectedProperty($validator, 'template'); + $this->assertSame('Msg', $actual); + + $actual = $this->getProtectedProperty($validator, 'templateChanged'); + $this->assertTrue($actual); + + $templates = ['name' => 'Name msg']; + $validator = new PresenceOf(['message' => &$templates]); + + $expected = ['name' => 'Name msg']; + $actual = $validator->getTemplates(); + $this->assertSame($expected, $actual); + } + /** * @author Phalcon Team * @since 2018-11-13