From e0381d0531dbaf2de464e8db158448abb9a93f56 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 15 Dec 2022 16:03:38 +0100 Subject: [PATCH] CallbackValidator: Cache callback results by default Since https://github.com/Icinga/ipl-html/pull/97 form elements don't cache the validation results anymore. This isn't a problem for most validators. Though, custom callbacks written before this change were written with the cache in mind. This change allows to control this when creating the validator. It caches by default for historical reasons. (To not break compatibility) --- src/CallbackValidator.php | 21 +++++++++++++++++++-- tests/CallbackValidatorTest.php | 30 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/CallbackValidator.php b/src/CallbackValidator.php index 611a45e..ec31f5c 100644 --- a/src/CallbackValidator.php +++ b/src/CallbackValidator.php @@ -25,21 +25,38 @@ class CallbackValidator extends BaseValidator /** @var callable Validation callback */ protected $callback; + /** @var bool Whether to cache the callback's result */ + protected $cacheResult; + + /** @var ?bool The result, if {@see self::$cacheResult} is `true` (default) */ + protected $result; + /** * Create a new callback validator * * @param callable $callback Validation callback + * @param boolean $cacheResult Whether to cache the callback's result */ - public function __construct(callable $callback) + public function __construct(callable $callback, bool $cacheResult = true) { $this->callback = $callback; + $this->cacheResult = $cacheResult; } public function isValid($value) { + if ($this->result !== null) { + return $this->result; + } + // Multiple isValid() calls must not stack validation messages $this->clearMessages(); - return call_user_func($this->callback, $value, $this); + $valid = (bool) call_user_func($this->callback, $value, $this); + if ($this->cacheResult) { + $this->result = $valid; + } + + return $valid; } } diff --git a/tests/CallbackValidatorTest.php b/tests/CallbackValidatorTest.php index 14dadac..d92c5dd 100644 --- a/tests/CallbackValidatorTest.php +++ b/tests/CallbackValidatorTest.php @@ -22,4 +22,34 @@ public function testWhetherValidationCallbackIsOnlyExecutedWhenIsValidIsCalled() $this->assertSame($messages, $validator->getMessages()); } + + public function testWhetherCallbackIsOnlyCalledAgainIfNotCached() + { + $count = 0; + + $validator = new CallbackValidator(function ($value, CallbackValidator $validator) use (&$count) { + $count++; + return true; + }); + + $validator->isValid(true); + $validator->isValid(true); + + $this->assertEquals(1, $count, 'The callback is called again even if the cache is enabled'); + } + + public function testWhetherCallbackIsCalledAgainIfCached() + { + $count = 0; + + $validator = new CallbackValidator(function ($value, CallbackValidator $validator) use (&$count) { + $count++; + return true; + }, false); + + $validator->isValid(true); + $validator->isValid(true); + + $this->assertEquals(2, $count, 'The callback is not called again even if the cache is disabled'); + } }