Skip to content

Commit

Permalink
Add a custom variable validator + protected props (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrm authored Apr 25, 2022
1 parent a0ff7a7 commit ef82911
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 10 deletions.
56 changes: 46 additions & 10 deletions src/NXP/MathExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,32 @@ class MathExecutor
*
* @var array<string, float|string>
*/
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<string, CustomFunction>
*/
private $functions = [];
protected $functions = [];

/**
* @var array<string, Token[]>
*/
private $cache = [];
protected $cache = [];

/**
* Base math operators
Expand All @@ -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();
}

Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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
*
Expand Down
15 changes: 15 additions & 0 deletions tests/MathTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit ef82911

Please sign in to comment.