diff --git a/src/Predicate/AbstractPredicate.php b/src/Predicate/AbstractPredicate.php index 01c92ba..99d5872 100644 --- a/src/Predicate/AbstractPredicate.php +++ b/src/Predicate/AbstractPredicate.php @@ -20,6 +20,11 @@ abstract class AbstractPredicate implements Predicate return new NegatedPredicate($this); } + public function negate(): Predicate + { + return $this->not(); + } + public function and(...$predicate): Predicate { array_unshift($predicate, $this); diff --git a/src/Predicate/ConstantPredicate.php b/src/Predicate/ConstantPredicate.php index 68eafd7..6a5a480 100644 --- a/src/Predicate/ConstantPredicate.php +++ b/src/Predicate/ConstantPredicate.php @@ -30,13 +30,15 @@ class ConstantPredicate extends AbstractPredicate public function not(): Predicate { - return new self(!$this->value); + return $this->value + ? self::never() + : self::always(); } public function and (...$predicate): Predicate { if (!$this->value) { - return new self(false); + return self::never(); } return all($predicate); @@ -45,7 +47,7 @@ class ConstantPredicate extends AbstractPredicate public function or (...$predicate): Predicate { if ($this->value) { - return new self(true); + return self::always(); } return any($predicate); @@ -58,11 +60,13 @@ class ConstantPredicate extends AbstractPredicate public static function always() { - return new static(true); + static $always; + return $always ? $always : $always = new static(true); } public static function never() { - return new static(false); + static $never; + return $never ? $never : $never = new static(false); } } \ No newline at end of file diff --git a/tests/ConstantPredicateTest.php b/tests/ConstantPredicateTest.php new file mode 100644 index 0000000..10a46f6 --- /dev/null +++ b/tests/ConstantPredicateTest.php @@ -0,0 +1,123 @@ + + * + * Full license available in separate LICENSE file + */ + +use function Kadet\Functional\predicate; +use Kadet\Functional\Predicate\ConstantPredicate; + +class ConstantPredicateTest extends PHPUnit\Framework\TestCase +{ + private function getTestPredicate() + { + return function ($arg = null) { + return is_bool($arg); + }; + } + + public function randomDataProvider() + { + return [ + ['x'], + [false], + [true], + [], + [(object)[]], + [false, true], + [null, true], + [2321321] + ]; + } + + /** + * @dataProvider randomDataProvider + */ + public function testNeverAndPredicate(...$args) + { + $predicate = ConstantPredicate::never()->and($this->getTestPredicate()); + + $this->assertFalse($predicate(...$args)); + } + + /** + * @dataProvider randomDataProvider + */ + public function testNeverOrPredicate(...$args) + { + $predicate = predicate($this->getTestPredicate()); + $tested = ConstantPredicate::never()->or($predicate); + + $this->assertSame($predicate(...$args), $tested(...$args)); + } + + /** + * @dataProvider randomDataProvider + */ + public function testAlwaysOrPredicate(...$args) + { + $predicate = ConstantPredicate::always()->or($this->getTestPredicate()); + + $this->assertTrue($predicate(...$args)); + } + + /** + * @dataProvider randomDataProvider + */ + public function testAlwaysAndPredicate(...$args) + { + $predicate = predicate($this->getTestPredicate()); + $tested = ConstantPredicate::always()->and($predicate); + + $this->assertSame($predicate(...$args), $tested(...$args)); + } + + /** + * @dataProvider randomDataProvider + */ + public function testNever(...$args) + { + $tested = ConstantPredicate::never(); + + $this->assertFalse($tested(...$args)); + } + + /** + * @dataProvider randomDataProvider + */ + public function testNotAlways(...$args) + { + $tested = ConstantPredicate::always()->not(); + + $this->assertFalse($tested(...$args)); + } + + /** + * @dataProvider randomDataProvider + */ + public function testNotNever(...$args) + { + $tested = ConstantPredicate::never()->not(); + + $this->assertTrue($tested(...$args)); + } + + /** + * @dataProvider randomDataProvider + */ + public function testAlways(...$args) + { + $tested = ConstantPredicate::always(); + + $this->assertTrue($tested(...$args)); + } + + public function testAliases() + { + $this->assertSame(\Kadet\Functional\always(), ConstantPredicate::always()); + $this->assertSame(\Kadet\Functional\never(), ConstantPredicate::never()); + } +}