Skip to content

[FrameworkBundle] Inject the clock into comparison and range validators - #66683

Merged
nicolas-grekas merged 1 commit into
symfony:8.1from
lazerg:fix/issue-66681-validator-clock
Oct 7, 2026
Merged

nicolas-grekas merged 1 commit into
symfony:8.1from
lazerg:fix/issue-66681-validator-clock

Conversation

@lazerg

@lazerg lazerg commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor
Q A
Branch? 8.1
Bug fix? yes
New feature? no
Deprecations? no
Issues Fix #66681
License MIT

#63360 made the comparison validators and RangeValidator accept a clock, and bound ClockInterface on the validator prototype in validator.php. That prototype is abstract and tagged container.excluded, so it only exists for the translation extractor. AddConstraintValidatorsPass skips excluded services, the factory never finds these validators in its locator, and it builds them with new $name(). The binding is never used, so MockClock and ClockSensitiveTrait::mockTime() have no effect on bounds like '+48 hours'.

This registers RangeValidator and the eight comparison validators as concrete services that get clock, the same way validator.email or validator.when are registered. The property accessor argument stays null, as it was with new $name(). The dead binding is removed. DivisibleByValidator also extends AbstractComparisonValidator, but relative dates make no sense there, so I left it out.

The new test fails without the fix (1 violation instead of 0) and passes with it. ./phpunit src/Symfony/Bundle/FrameworkBundle passes (1486 tests, 3 skipped).

Merge-up to 8.2: the config moved to src/Symfony/Component/Validator/Resources/config/validator.php, and git applies the change there. Only its imports conflict: keep ConstantFunctionProvider and drop ClockInterface. FrameworkExtensionTestCase conflicts too: keep the 8.2 side and move the test to ValidationBundleTest, where it needs no version check (with the MockClock, GreaterThan, LessThan and Range imports):

public function testComparisonAndRangeValidatorsUseTheClock()
{
    $container = $this->load([], merge: false);
    $container->register('clock', MockClock::class)->setArguments(['2020-01-01 12:00:00']);
    $container->setAlias('validator.alias', 'validator')->setPublic(true);
    $container->compile();

    $validator = $container->get('validator.alias');
    $value = new \DateTimeImmutable('2020-02-01');

    $this->assertCount(0, $validator->validate($value, new Range(min: '+48 hours', max: '+1 year')));
    $this->assertCount(0, $validator->validate($value, new GreaterThan('+48 hours')));
    $this->assertCount(0, $validator->validate($value, new LessThan('+1 year')));
}

Checked on 8.2: the test fails without the change and passes with it.

@nicolas-grekas
nicolas-grekas force-pushed the fix/issue-66681-validator-clock branch from aabc8a0 to 0cbd9cf Compare October 7, 2026 14:02
@nicolas-grekas

Copy link
Copy Markdown
Member

Thank you @lazerg.

@nicolas-grekas
nicolas-grekas merged commit 194b95e into symfony:8.1 Oct 7, 2026
13 checks passed
@fabpot fabpot mentioned this pull request Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants