add basic predicates

This commit is contained in:
Kacper Donat 2018-07-08 18:05:25 +02:00
parent 4820e9fdb4
commit 804dd0e0e4
10 changed files with 1668 additions and 28 deletions

View File

@ -20,7 +20,8 @@
"Kadet\\Functional\\": "./src/"
},
"files": [
"./src/functions.php"
"./src/functions.php",
"./src/Predicates/index.php"
]
}
}

1474
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -23,12 +23,12 @@ abstract class AbstractPredicate implements Predicate
public function and(...$predicate): Predicate
{
array_unshift($predicate, $this);
return all($predicate);
return all(...$predicate);
}
public function or(...$predicate): Predicate
{
array_unshift($predicate, $this);
return any($predicate);
return any(...$predicate);
}
}

View File

@ -28,7 +28,7 @@ class AllOfPredicate extends AbstractPredicate
public function and(...$predicate): Predicate
{
$predicate = array_merge($this->predicates, $predicate);
return parent::and($predicate);
return parent::and(...$predicate);
}
public function __invoke(...$args): bool

View File

@ -28,7 +28,7 @@ class AnyOfPredicate extends AbstractPredicate
public function or(...$predicate): Predicate
{
$predicate = array_merge($this->predicates, $predicate);
return parent::or($predicate);
return parent::or(...$predicate);
}

View File

@ -23,7 +23,7 @@ class ConstantPredicate extends AbstractPredicate
*
* @param bool $value
*/
public function __construct(bool $value)
private function __construct(bool $value)
{
$this->value = $value;
}
@ -55,4 +55,14 @@ class ConstantPredicate extends AbstractPredicate
{
return $this->value;
}
public static function always()
{
return new static(true);
}
public static function never()
{
return new static(false);
}
}

View File

@ -0,0 +1,91 @@
<?php
/**
* Copyright 2018 Kacper Donat
*
* @author Kacper "Kadet" Donat <kacper@kadet.net>
*
* Full license available in separate LICENSE file
*/
namespace Kadet\Functional\Predicates;
use Kadet\Functional\Predicate;
use function Kadet\Functional\predicate;
/**
* @param $expected
*
* @return \Kadet\Functional\Predicate
* @throws \Exception
*/
function equals($expected): Predicate
{
return predicate(function ($value) use ($expected) {
return $expected == $value;
});
}
/**
* @param $expected
*
* @return \Kadet\Functional\Predicate
* @throws \Exception
*/
function same($expected): Predicate
{
return predicate(function ($value) use ($expected) {
return $value === $expected;
});
}
/**
* @param $expected
*
* @return \Kadet\Functional\Predicate
* @throws \Exception
*/
function gt($expected): Predicate
{
return predicate(function ($value) use ($expected) {
return $value > $expected;
});
}
/**
* @param $expected
*
* @return \Kadet\Functional\Predicate
* @throws \Exception
*/
function ge($expected): Predicate
{
return predicate(function ($value) use ($expected) {
return $value >= $expected;
});
}
/**
* @param $expected
*
* @return \Kadet\Functional\Predicate
* @throws \Exception
*/
function lt($expected): Predicate
{
return predicate(function ($value) use ($expected) {
return $value < $expected;
});
}
/**
* @param $expected
*
* @return \Kadet\Functional\Predicate
* @throws \Exception
*/
function le($expected): Predicate
{
return predicate(function ($value) use ($expected) {
return $value <= $expected;
});
}

11
src/Predicates/index.php Normal file
View File

@ -0,0 +1,11 @@
<?php
/**
* Copyright 2018 Kacper Donat
*
* @author Kacper "Kadet" Donat <kacper@kadet.net>
*
* Full license available in separate LICENSE file
*/
require_once __DIR__."/comparisons.php";
require_once __DIR__."/objects.php";

View File

@ -0,0 +1,57 @@
<?php
/**
* Copyright 2018 Kacper Donat
*
* @author Kacper "Kadet" Donat <kacper@kadet.net>
*
* Full license available in separate LICENSE file
*/
namespace Kadet\Functional\Predicates;
use function Kadet\Functional\predicate;
use Kadet\Functional\Predicate\ClosurePredicate;
/**
* @param string $method
* @param $predicate
* @param array $args
*
* @return \Kadet\Functional\Predicate
*/
function method(string $method, $predicate, ...$args)
{
$predicate = predicate($predicate);
return new ClosurePredicate(function ($object) use ($method, $predicate, $args) {
return $predicate($object->{$method}($args));
});
}
/**
* @param string $property
* @param $predicate
*
* @return \Kadet\Functional\Predicate
*/
function property(string $property, $predicate) {
$predicate = predicate($predicate);
return new ClosurePredicate(function ($object) use ($property, $predicate) {
if (isset($object->$property)) {
return $predicate($object->$property);
} elseif (method_exists($object, $getter = 'get'.ucfirst($property))) {
return $predicate($object->$getter());
} else {
return false;
}
});
}
function instance(string $class)
{
return new ClosurePredicate(function ($value) use ($class) {
return $value instanceof $class;
});
}

View File

@ -11,20 +11,17 @@ use Kadet\Functional\Predicate\ConstantPredicate;
* @param $predicate
*
* @return \Kadet\Functional\Predicate
* @throws \Exception
*/
function predicate($predicate): Predicate
{
if ($predicate instanceof Predicate) {
return $predicate;
switch (true) {
case $predicate instanceof Predicate:
return $predicate;
case is_callable($predicate):
return new ClosurePredicate(\Closure::fromCallable($predicate));
default:
throw new \InvalidArgumentException('$predicate is not valid predicate.');
}
if (is_callable($predicate)) {
return new ClosurePredicate(\Closure::fromCallable($predicate));
}
// todo better exception
throw new \Exception();
}
function not($predicate)
@ -34,30 +31,29 @@ function not($predicate)
function always()
{
return new ConstantPredicate(true);
return ConstantPredicate::always();
}
function never()
{
return new ConstantPredicate(false);
return ConstantPredicate::never();
}
function unpack($arguments)
{
return count($arguments) === 1 && is_array(reset($arguments))
? reset($arguments)
: $arguments;
}
function all(...$predicates)
{
// extract array
if (count($predicates) === 1 && is_array($predicates[0])) {
$predicates = $predicates[0];
}
$predicates = unpack($predicates);
return new AllOfPredicate(...array_map(predicate::class, $predicates));
}
function any(...$predicates)
{
// extract array
if (count($predicates) === 1 && is_array($predicates[0])) {
$predicates = $predicates[0];
}
$predicates = unpack($predicates);
return new AnyOfPredicate(...array_map(predicate::class, $predicates));
}