diff --git a/src/NXP/MathExecutor.php b/src/NXP/MathExecutor.php index a113275..ab550fa 100644 --- a/src/NXP/MathExecutor.php +++ b/src/NXP/MathExecutor.php @@ -31,27 +31,32 @@ class MathExecutor * * @var array */ - private $variables = []; + protected $variables = []; /** * @var callable|null */ - private $onVarNotFound = null; + protected $onVarNotFound = null; + + /** + * @var callable|null + */ + protected $onVarValidation = null; /** * @var Operator[] */ - private $operators = []; + protected $operators = []; /** * @var array */ - private $functions = []; + protected $functions = []; /** * @var array */ - private $cache = []; + protected $cache = []; /** * Base math operators @@ -74,6 +79,8 @@ protected function addDefaults(): void foreach ($this->defaultFunctions() as $name => $callable) { $this->addFunction($name, $callable); } + + $this->onVarValidation = [$this, 'defaultVarValidation']; $this->variables = $this->defaultVars(); } @@ -507,23 +514,37 @@ public function getVar(string $variable) } /** - * Add variable to executor + * Add variable to executor. To set a custom validator use setVarValidationHandler. * * @param string $variable - * @param int|float $value + * @param $value * @return MathExecutor + * @throws MathExecutorException if the value is invalid based on the default or custom validator */ public function setVar(string $variable, $value): self { - if (!is_scalar($value) && $value !== null) { - $type = gettype($value); - throw new MathExecutorException("Variable ({$variable}) type ({$type}) is not scalar"); + if ($this->onVarValidation) { + call_user_func($this->onVarValidation, $variable, $value); } $this->variables[$variable] = $value; return $this; } + /** + * Default variable validation, ensures that the value is a scalar. + * @param string $variable + * @param $value + * @throws MathExecutorException if the value is not a scalar + */ + protected function defaultVarValidation(string $variable, $value): void + { + if (!is_scalar($value) && $value !== null) { + $type = gettype($value); + throw new MathExecutorException("Variable ({$variable}) type ({$type}) is not scalar"); + } + } + /** * Test to see if a variable exists * @@ -567,6 +588,21 @@ public function setVarNotFoundHandler(callable $handler): self return $this; } + /** + * Define a validation method that will be invoked when a variable is set using setVar. + * The first parameter will be the variable name, and the second will be the variable value. + * Set to null to disable validation. + * + * @param ?callable $handler throws a MathExecutorException in case of an invalid variable + * + * @return MathExecutor + */ + public function setVarValidationHandler(?callable $handler): self + { + $this->onVarValidation = $handler; + return $this; + } + /** * Remove variable from executor * diff --git a/tests/MathTest.php b/tests/MathTest.php index 3eca351..14de2bf 100644 --- a/tests/MathTest.php +++ b/tests/MathTest.php @@ -589,6 +589,21 @@ public function testSetVarsDoesNotAcceptResource() $calculator->setVar('resource', tmpfile()); } + public function testSetCustomVarValidator() + { + $calculator = new MathExecutor(); + $calculator->setVarValidationHandler(function ($name, $variable) { + if ($name === 'invalidVar' && $variable === 'invalid') { + throw new MathExecutorException("Invalid variable"); + } + }); + + $calculator->setVar('valid', $this); + + $this->expectException(MathExecutorException::class); + $calculator->setVar('invalidVar', 'invalid'); + } + public function testVarExists() { $calculator = new MathExecutor();