Skip to content

Commit 0b78da6

Browse files
committed
Add math operators, rename == / === to align naming in PHP official doc
1 parent 1ccb073 commit 0b78da6

17 files changed

+468
-13
lines changed

src/OperatorManager.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ protected function buildins(): array
3737
'missing_some' => null,
3838
// Logic and Boolean Operations
3939
'if' => null,
40-
'==' => Operators\Equals::class,
41-
'===' => Operators\Same::class,
42-
'!=' => Operators\NotEquals::class,
43-
'!==' => Operators\NotSame::class,
40+
'==' => Operators\Equal::class,
41+
'===' => Operators\Identical::class,
42+
'!=' => Operators\NotEqual::class,
43+
'!==' => Operators\NotIdentical::class,
4444
'!' => Operators\Not::class,
4545
'!!' => Operators\Booleanify::class,
4646
'or' => Operators\OrOperator::class,
@@ -52,11 +52,11 @@ protected function buildins(): array
5252
'<=' => Operators\LessThanOrEqual::class,
5353
'max' => null,
5454
'min' => null,
55-
'+' => null,
56-
'-' => null,
57-
'*' => null,
58-
'/' => null,
59-
'%' => null,
55+
'+' => Operators\Plus::class,
56+
'-' => Operators\Minus::class,
57+
'*' => Operators\Multiply::class,
58+
'/' => Operators\Divide::class,
59+
'%' => Operators\Modulo::class,
6060
// Array Operations
6161
'map' => null,
6262
'reduce' => null,

src/Operators/Divide.php

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
namespace JsonLogic\Operators;
3+
4+
use Closure;
5+
use JsonLogic\Parameters;
6+
7+
/**
8+
* @operator /
9+
*/
10+
class Divide extends Operator
11+
{
12+
protected $alias = '/';
13+
14+
public function params($param): Closure
15+
{
16+
$this->autoValidateParams($param);
17+
$prepared = Parameters::from($param);
18+
19+
return function (&$data) use (&$prepared) {
20+
return $prepared->reduce(function ($a, $b) {
21+
return $a / $b;
22+
}, $data);
23+
};
24+
}
25+
}

src/Operators/Equals.php renamed to src/Operators/Equal.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/**
88
* @operator ==
99
*/
10-
class Equals extends Operator
10+
class Equal extends Operator
1111
{
1212
protected $alias = '==';
1313
protected $minParamCounts = 2;

src/Operators/Same.php renamed to src/Operators/Identical.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/**
88
* @operator ===
99
*/
10-
class Same extends Operator
10+
class Identical extends Operator
1111
{
1212
protected $alias = '===';
1313
protected $minParamCounts = 2;

src/Operators/Minus.php

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
namespace JsonLogic\Operators;
3+
4+
use Closure;
5+
use JsonLogic\Parameters;
6+
7+
/**
8+
* @operator -
9+
*/
10+
class Minus extends Operator
11+
{
12+
protected $alias = '-';
13+
14+
public function params($param): Closure
15+
{
16+
$this->autoValidateParams($param);
17+
$prepared = Parameters::from($param);
18+
19+
return function (&$data) use (&$prepared) {
20+
return $prepared->reduce(function ($a, $b) {
21+
return $a - $b;
22+
}, $data);
23+
};
24+
}
25+
}

src/Operators/Modulo.php

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
namespace JsonLogic\Operators;
3+
4+
use Closure;
5+
use JsonLogic\Parameters;
6+
7+
/**
8+
* @operator %
9+
*/
10+
class Modulo extends Operator
11+
{
12+
protected $alias = '%';
13+
14+
public function params($param): Closure
15+
{
16+
$this->autoValidateParams($param);
17+
$prepared = Parameters::from($param);
18+
19+
return function (&$data) use (&$prepared) {
20+
return $prepared->reduce(function ($a, $b) {
21+
return $a % $b;
22+
}, $data);
23+
};
24+
}
25+
}

src/Operators/Multiply.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
namespace JsonLogic\Operators;
3+
4+
use Closure;
5+
use JsonLogic\Parameters;
6+
7+
/**
8+
* @operator *
9+
*/
10+
class Multiply extends Operator
11+
{
12+
protected $alias = '*';
13+
14+
public function params($param): Closure
15+
{
16+
$this->autoValidateParams($param);
17+
$prepared = Parameters::from($param);
18+
19+
return function (&$data) use (&$prepared) {
20+
return array_product($prepared->values($data));
21+
};
22+
}
23+
}

src/Operators/NotEquals.php renamed to src/Operators/NotEqual.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/**
88
* @operator !=
99
*/
10-
class NotEquals extends Operator
10+
class NotEqual extends Operator
1111
{
1212
protected $alias = '!=';
1313
protected $minParamCounts = 2;

src/Operators/NotSame.php renamed to src/Operators/NotIdentical.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/**
88
* @operator !==
99
*/
10-
class NotSame extends Operator
10+
class NotIdentical extends Operator
1111
{
1212
protected $alias = '!==';
1313
protected $minParamCounts = 2;

src/Operators/Plus.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
namespace JsonLogic\Operators;
3+
4+
use Closure;
5+
use JsonLogic\Parameters;
6+
7+
/**
8+
* @operator +
9+
*/
10+
class Plus extends Operator
11+
{
12+
protected $alias = '+';
13+
14+
public function params($param): Closure
15+
{
16+
$this->autoValidateParams($param);
17+
$prepared = Parameters::from($param);
18+
19+
return function (&$data) use (&$prepared) {
20+
return array_sum($prepared->values($data));
21+
};
22+
}
23+
}

src/Parameters.php

+22
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,28 @@ public function everyPairs(callable $fn, &$data): bool
3737
);
3838
}
3939

40+
public function reduce(callable $fn, &$data, $init = null)
41+
{
42+
return is_null($init)
43+
? array_reduce(
44+
array_slice($this->params, 1),
45+
function ($curry, $closure) use (&$data, &$fn) {
46+
return $fn($curry, $closure($data));
47+
},
48+
$this->params[0]($data)
49+
)
50+
: array_reduce($this->params, function ($curry, $closure) use (&$data, &$fn) {
51+
return $fn($curry, $closure($data));
52+
}, $init);
53+
}
54+
55+
public function values(&$data): array
56+
{
57+
return array_map(function ($getter) use (&$data) {
58+
return $getter($data);
59+
}, $this->params);
60+
}
61+
4062
private function recurseEvery(callable &$fn, &$data, Closure &$getter = null, Closure &...$rest): bool
4163
{
4264
return $getter
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
namespace Tests\JsonLogic\Operators;
3+
4+
use JsonLogic\Operators\Divide;
5+
use Tests\TestCase;
6+
7+
use function number_format;
8+
9+
/**
10+
* @group operators
11+
*/
12+
class DivideTest extends TestCase
13+
{
14+
/** @dataProvider cases */
15+
public function test(array $params, $data, string $expect): void
16+
{
17+
$this->assertSame(
18+
$expect,
19+
number_format((new Divide())->params($params)($data), 3)
20+
);
21+
}
22+
23+
public function cases(): array
24+
{
25+
return [
26+
'1 ÷ 1' => [[1, 1], null, '1.000'],
27+
'3.1415926 ÷ 2.7182818' => [[3.1415926, 2.7182818], null, '1.156'],
28+
'5/7 ÷ 25/49' => [[5/7, 25/49], null, '1.400'],
29+
'1/2 ÷ 3/2 ÷ 4/3 ÷ 5/4' => [[1/2, 3/2, 4/3, 5/4], null, '0.200'],
30+
'Pi ÷ e' => [
31+
[
32+
['var' => 'real.irrational.Pi'],
33+
['var' => 'real.irrational.e'],
34+
],
35+
[
36+
'real' => [
37+
'irrational' => [
38+
'Pi' => 3.1415926,
39+
'e' => 2.7182818,
40+
],
41+
],
42+
],
43+
'1.156',
44+
],
45+
];
46+
}
47+
}
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
namespace Tests\JsonLogic\Operators;
3+
4+
use JsonLogic\Operators\Minus;
5+
use Tests\TestCase;
6+
7+
use function number_format;
8+
9+
/**
10+
* @group operators
11+
*/
12+
class MinusTest extends TestCase
13+
{
14+
/** @dataProvider cases */
15+
public function test(array $params, $data, string $expect): void
16+
{
17+
$this->assertSame(
18+
$expect,
19+
number_format((new Minus())->params($params)($data), 2)
20+
);
21+
}
22+
23+
public function cases(): array
24+
{
25+
return [
26+
'1 - 1' => [[1, 1], null, '0.00'],
27+
'3.1415926 - 2.7182818' => [[3.1415926, 2.7182818], null, '0.42'],
28+
'1/3 - 2/3' => [[1/3, 2/3], null, '-0.33'],
29+
'1/2 - 1/3 - 1/4 - 1/5 - 1/6' => [[1/2, 1/3, 1/4, 1/5, 1/6], null, '-0.45'],
30+
'Pi - e' => [
31+
[
32+
['var' => 'real.irrational.Pi'],
33+
['var' => 'real.irrational.e'],
34+
],
35+
[
36+
'real' => [
37+
'irrational' => [
38+
'Pi' => 3.1415926,
39+
'e' => 2.7182818,
40+
],
41+
],
42+
],
43+
'0.42',
44+
],
45+
];
46+
}
47+
}
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
namespace Tests\JsonLogic\Operators;
3+
4+
use JsonLogic\Operators\Modulo;
5+
use Tests\TestCase;
6+
7+
/**
8+
* @group operators
9+
*/
10+
class ModuloTest extends TestCase
11+
{
12+
/** @dataProvider cases */
13+
public function test(array $params, $data, int $expect): void
14+
{
15+
$this->assertSame(
16+
$expect,
17+
(new Modulo())->params($params)($data)
18+
);
19+
}
20+
21+
public function cases(): array
22+
{
23+
return [
24+
'1 % 1' => [[1, 1], null, 0],
25+
'100 % 3' => [[100, 3], null, 1],
26+
'100 % 23 % 17 % 5' => [[100, 23, 17, 5], null, 3],
27+
'100 % 17' => [
28+
[
29+
['var' => 'one hundred'],
30+
['var' => 'seventeen'],
31+
],
32+
[
33+
'one hundred' => 100,
34+
'seventeen' => 17,
35+
],
36+
15,
37+
],
38+
];
39+
}
40+
}

0 commit comments

Comments
 (0)