Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG-5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 10 additions & 4 deletions phalcon/Filter/Validation/AbstractValidator.zep
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
99 changes: 99 additions & 0 deletions tests/unit/Filter/Validation/Validator/ConstructTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 <team@phalcon.io>
* @since 2018-11-13
Expand Down Expand Up @@ -120,6 +169,56 @@ public function testFilterValidationValidatorConstruct(): void
$this->assertSame($expected, $actual);
}

/**
* @author Phalcon Team <team@phalcon.io>
* @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 <team@phalcon.io>
* @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 <team@phalcon.io>
* @since 2018-11-13
Expand Down
Loading