Adding varExists method and support for undefined var handler in getVar (#96)
* Added varExists method * getVar now respects VarNotFoundHandler setting * Use local version of PHP-CS-Fixer Instead of hard coded version from github actions * Fixing actions * Fixing actions * Dropping testing for 7.3, as it is no longer supported
This commit is contained in:
parent
6ebe4849ff
commit
a0ff7a79af
9 changed files with 79 additions and 51 deletions
8
.github/workflows/tests.yml
vendored
8
.github/workflows/tests.yml
vendored
|
@ -8,7 +8,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php: [8.1, 8.0, 7.4, 7.3]
|
||||
php: [8.1, 8.0, 7.4]
|
||||
dependency-version: [prefer-lowest, prefer-stable]
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
|
||||
|
@ -34,7 +34,7 @@ jobs:
|
|||
run: vendor/bin/phpunit
|
||||
|
||||
- name: PHP CS Fixer
|
||||
uses: StephaneBour/actions-php-cs-fixer@1.0
|
||||
if: matrix.os != 'windows-latest'
|
||||
with:
|
||||
dir: './src'
|
||||
run: |
|
||||
vendor/bin/php-cs-fixer fix --dry-run -v ./src
|
||||
vendor/bin/php-cs-fixer fix --dry-run -v ./tests
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,3 +3,5 @@ vendor/
|
|||
composer.lock
|
||||
.phpunit.result.cache
|
||||
.vscode
|
||||
.php-cs-fixer.cache
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
"php": ">=7.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": ">=9.0"
|
||||
"phpunit/phpunit": ">=9.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace NXP\Classes;
|
||||
|
||||
use NXP\Exception\IncorrectNumberOfFunctionParametersException;
|
||||
|
@ -49,7 +48,7 @@ class CustomFunction
|
|||
*
|
||||
* @throws IncorrectNumberOfFunctionParametersException
|
||||
*/
|
||||
public function execute(array &$stack) : Token
|
||||
public function execute(array &$stack): Token
|
||||
{
|
||||
if (count($stack) < $this->places) {
|
||||
throw new IncorrectNumberOfFunctionParametersException($this->name);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace NXP\Classes;
|
||||
|
||||
use NXP\Exception\IncorrectExpressionException;
|
||||
|
@ -55,7 +54,7 @@ class Operator
|
|||
*
|
||||
* @throws IncorrectExpressionException
|
||||
*/
|
||||
public function execute(array &$stack) : Token
|
||||
public function execute(array &$stack): Token
|
||||
{
|
||||
if (count($stack) < $this->places) {
|
||||
throw new IncorrectExpressionException();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace NXP\Classes;
|
||||
|
||||
class Token
|
||||
|
|
|
@ -66,7 +66,7 @@ class Tokenizer
|
|||
$this->operators = $operators;
|
||||
}
|
||||
|
||||
public function tokenize() : self
|
||||
public function tokenize(): self
|
||||
{
|
||||
foreach (str_split($this->input, 1) as $ch) {
|
||||
switch (true) {
|
||||
|
@ -184,17 +184,17 @@ class Tokenizer
|
|||
return $this;
|
||||
}
|
||||
|
||||
private function isNumber(string $ch) : bool
|
||||
private function isNumber(string $ch): bool
|
||||
{
|
||||
return $ch >= '0' && $ch <= '9';
|
||||
}
|
||||
|
||||
private function isAlpha(string $ch) : bool
|
||||
private function isAlpha(string $ch): bool
|
||||
{
|
||||
return $ch >= 'a' && $ch <= 'z' || $ch >= 'A' && $ch <= 'Z' || $ch == '_';
|
||||
}
|
||||
|
||||
private function emptyNumberBufferAsLiteral() : void
|
||||
private function emptyNumberBufferAsLiteral(): void
|
||||
{
|
||||
if (strlen($this->numberBuffer)) {
|
||||
$this->tokens[] = new Token(Token::Literal, $this->numberBuffer);
|
||||
|
@ -202,22 +202,22 @@ class Tokenizer
|
|||
}
|
||||
}
|
||||
|
||||
private function isDot(string $ch) : bool
|
||||
private function isDot(string $ch): bool
|
||||
{
|
||||
return $ch == '.';
|
||||
}
|
||||
|
||||
private function isLP(string $ch) : bool
|
||||
private function isLP(string $ch): bool
|
||||
{
|
||||
return $ch == '(';
|
||||
}
|
||||
|
||||
private function isRP(string $ch) : bool
|
||||
private function isRP(string $ch): bool
|
||||
{
|
||||
return $ch == ')';
|
||||
}
|
||||
|
||||
private function emptyStrBufferAsVariable() : void
|
||||
private function emptyStrBufferAsVariable(): void
|
||||
{
|
||||
if ($this->stringBuffer != '') {
|
||||
$this->tokens[] = new Token(Token::Variable, $this->stringBuffer);
|
||||
|
@ -225,7 +225,7 @@ class Tokenizer
|
|||
}
|
||||
}
|
||||
|
||||
private function isComma(string $ch) : bool
|
||||
private function isComma(string $ch): bool
|
||||
{
|
||||
return $ch == ',';
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ class Tokenizer
|
|||
* @throws IncorrectBracketsException
|
||||
* @throws UnknownOperatorException
|
||||
*/
|
||||
public function buildReversePolishNotation() : array
|
||||
public function buildReversePolishNotation(): array
|
||||
{
|
||||
$tokens = [];
|
||||
/** @var SplStack<Token> $stack */
|
||||
|
|
|
@ -65,7 +65,7 @@ class MathExecutor
|
|||
* Set default operands and functions
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
protected function addDefaults() : void
|
||||
protected function addDefaults(): void
|
||||
{
|
||||
foreach ($this->defaultOperators() as $name => $operator) {
|
||||
[$callable, $priority, $isRightAssoc] = $operator;
|
||||
|
@ -82,7 +82,7 @@ class MathExecutor
|
|||
*
|
||||
* @return array<string, array{callable, int, bool}>
|
||||
*/
|
||||
protected function defaultOperators() : array
|
||||
protected function defaultOperators(): array
|
||||
{
|
||||
return [
|
||||
'+' => [
|
||||
|
@ -210,7 +210,7 @@ class MathExecutor
|
|||
* @param Operator $operator
|
||||
* @return MathExecutor
|
||||
*/
|
||||
public function addOperator(Operator $operator) : self
|
||||
public function addOperator(Operator $operator): self
|
||||
{
|
||||
$this->operators[$operator->operator] = $operator;
|
||||
return $this;
|
||||
|
@ -222,7 +222,7 @@ class MathExecutor
|
|||
*
|
||||
* @return array<callable>
|
||||
*/
|
||||
protected function defaultFunctions() : array
|
||||
protected function defaultFunctions(): array
|
||||
{
|
||||
return [
|
||||
'abs' => function ($arg) {
|
||||
|
@ -459,7 +459,7 @@ class MathExecutor
|
|||
* @return MathExecutor
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function addFunction(string $name, ?callable $function = null, ?int $places = null) : self
|
||||
public function addFunction(string $name, ?callable $function = null, ?int $places = null): self
|
||||
{
|
||||
$this->functions[$name] = new CustomFunction($name, $function, $places);
|
||||
return $this;
|
||||
|
@ -470,7 +470,7 @@ class MathExecutor
|
|||
*
|
||||
* @return array<string, float>
|
||||
*/
|
||||
protected function defaultVars() : array
|
||||
protected function defaultVars(): array
|
||||
{
|
||||
return [
|
||||
'pi' => 3.14159265359,
|
||||
|
@ -483,7 +483,7 @@ class MathExecutor
|
|||
*
|
||||
* @return array<string, float|string>
|
||||
*/
|
||||
public function getVars() : array
|
||||
public function getVars(): array
|
||||
{
|
||||
return $this->variables;
|
||||
}
|
||||
|
@ -493,11 +493,14 @@ class MathExecutor
|
|||
*
|
||||
* @param string $variable
|
||||
* @return integer|float
|
||||
* @throws UnknownVariableException
|
||||
* @throws UnknownVariableException if VarNotFoundHandler is not set
|
||||
*/
|
||||
public function getVar(string $variable)
|
||||
{
|
||||
if (!array_key_exists($variable, $this->variables)) {
|
||||
if ($this->onVarNotFound) {
|
||||
return call_user_func($this->onVarNotFound, $variable);
|
||||
}
|
||||
throw new UnknownVariableException("Variable ({$variable}) not set");
|
||||
}
|
||||
return $this->variables[$variable];
|
||||
|
@ -510,7 +513,7 @@ class MathExecutor
|
|||
* @param int|float $value
|
||||
* @return MathExecutor
|
||||
*/
|
||||
public function setVar(string $variable, $value) : self
|
||||
public function setVar(string $variable, $value): self
|
||||
{
|
||||
if (!is_scalar($value) && $value !== null) {
|
||||
$type = gettype($value);
|
||||
|
@ -521,6 +524,16 @@ class MathExecutor
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if a variable exists
|
||||
*
|
||||
* @param string $variable
|
||||
*/
|
||||
public function varExists(string $variable): bool
|
||||
{
|
||||
return array_key_exists($variable, $this->variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add variables to executor
|
||||
*
|
||||
|
@ -529,7 +542,7 @@ class MathExecutor
|
|||
* @return MathExecutor
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setVars(array $variables, bool $clear = true) : self
|
||||
public function setVars(array $variables, bool $clear = true): self
|
||||
{
|
||||
if ($clear) {
|
||||
$this->removeVars();
|
||||
|
@ -560,7 +573,7 @@ class MathExecutor
|
|||
* @param string $variable
|
||||
* @return MathExecutor
|
||||
*/
|
||||
public function removeVar(string $variable) : self
|
||||
public function removeVar(string $variable): self
|
||||
{
|
||||
unset($this->variables[$variable]);
|
||||
return $this;
|
||||
|
@ -570,7 +583,7 @@ class MathExecutor
|
|||
* Remove all variables and the variable not found handler
|
||||
* @return MathExecutor
|
||||
*/
|
||||
public function removeVars() : self
|
||||
public function removeVars(): self
|
||||
{
|
||||
$this->variables = [];
|
||||
$this->onVarNotFound = null;
|
||||
|
@ -593,7 +606,7 @@ class MathExecutor
|
|||
* @return array<string, CustomFunction> containing callback and places indexed by
|
||||
* function name
|
||||
*/
|
||||
public function getFunctions() : array
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return $this->functions;
|
||||
}
|
||||
|
@ -603,7 +616,7 @@ class MathExecutor
|
|||
*
|
||||
* @return MathExecutor
|
||||
*/
|
||||
public function setDivisionByZeroIsZero() : self
|
||||
public function setDivisionByZeroIsZero(): self
|
||||
{
|
||||
$this->addOperator(new Operator("/", false, 180, function ($a, $b) {
|
||||
if ($b == 0) {
|
||||
|
@ -618,7 +631,7 @@ class MathExecutor
|
|||
* Get cache array with tokens
|
||||
* @return array<string, Token[]>
|
||||
*/
|
||||
public function getCache() : array
|
||||
public function getCache(): array
|
||||
{
|
||||
return $this->cache;
|
||||
}
|
||||
|
@ -626,7 +639,7 @@ class MathExecutor
|
|||
/**
|
||||
* Clear token's cache
|
||||
*/
|
||||
public function clearCache() : void
|
||||
public function clearCache(): void
|
||||
{
|
||||
$this->cache = [];
|
||||
}
|
||||
|
|
|
@ -499,6 +499,15 @@ class MathTest extends TestCase
|
|||
}
|
||||
);
|
||||
$this->assertEquals(15, $calculator->execute('5 * undefined'));
|
||||
$this->assertEquals(3, $calculator->getVar('undefined'));
|
||||
$this->assertNull($calculator->getVar('Lucy'));
|
||||
}
|
||||
|
||||
public function testGetVarException()
|
||||
{
|
||||
$calculator = new MathExecutor();
|
||||
$this->expectException(UnknownVariableException::class);
|
||||
$this->assertNull($calculator->getVar('Lucy'));
|
||||
}
|
||||
|
||||
public function testMinusZero()
|
||||
|
@ -580,6 +589,15 @@ class MathTest extends TestCase
|
|||
$calculator->setVar('resource', tmpfile());
|
||||
}
|
||||
|
||||
public function testVarExists()
|
||||
{
|
||||
$calculator = new MathExecutor();
|
||||
$varName = 'Eythel';
|
||||
$calculator->setVar($varName, 1);
|
||||
$this->assertTrue($calculator->varExists($varName));
|
||||
$this->assertFalse($calculator->varExists('Lucy'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerExpressionValues
|
||||
*/
|
||||
|
@ -662,8 +680,5 @@ class MathTest extends TestCase
|
|||
|
||||
$this->assertEquals(2048, $calculator->execute('2 ^ 11', false));
|
||||
$this->assertEquals(0, count($calculator->getCache()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue