proof of concept
This commit is contained in:
commit
40f8bfeab8
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
/.idea/
|
||||||
|
|
||||||
|
# PHP
|
||||||
|
/vendor/
|
||||||
|
/node_modules/
|
||||||
|
|
||||||
|
test.*.php
|
26
composer.json
Normal file
26
composer.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "kadet/predicate",
|
||||||
|
"description": "Functional library for PHP",
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Kacper Donat",
|
||||||
|
"email": "kadet1090@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^7.0"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Kadet\\Functional\\": "./src/"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"./src/functions.php"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
21
src/Predicate.php
Normal file
21
src/Predicate.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright 2018 Kacper Donat
|
||||||
|
*
|
||||||
|
* @author Kacper "Kadet" Donat <kacper@kadet.net>
|
||||||
|
*
|
||||||
|
* Full license available in separate LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Kadet\Functional;
|
||||||
|
|
||||||
|
|
||||||
|
interface Predicate
|
||||||
|
{
|
||||||
|
public function __invoke(...$args): bool;
|
||||||
|
|
||||||
|
public function not(): Predicate;
|
||||||
|
|
||||||
|
public function and(...$predicate): Predicate;
|
||||||
|
public function or(...$predicate): Predicate;
|
||||||
|
}
|
34
src/Predicate/AbstractPredicate.php
Normal file
34
src/Predicate/AbstractPredicate.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright 2018 Kacper Donat
|
||||||
|
*
|
||||||
|
* @author Kacper "Kadet" Donat <kacper@kadet.net>
|
||||||
|
*
|
||||||
|
* Full license available in separate LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Kadet\Functional\Predicate;
|
||||||
|
|
||||||
|
|
||||||
|
use Kadet\Functional\Predicate;
|
||||||
|
use function Kadet\Functional\predicate;
|
||||||
|
|
||||||
|
abstract class AbstractPredicate implements Predicate
|
||||||
|
{
|
||||||
|
public function not(): Predicate
|
||||||
|
{
|
||||||
|
return new NegatedPredicate($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function and(...$predicate): Predicate
|
||||||
|
{
|
||||||
|
array_unshift($predicate, $this);
|
||||||
|
return new AllOfPredicate(...array_map(predicate::class, $predicate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function or(...$predicate): Predicate
|
||||||
|
{
|
||||||
|
array_unshift($predicate, $this);
|
||||||
|
return new AnyOfPredicate(...array_map(predicate::class, $predicate));
|
||||||
|
}
|
||||||
|
}
|
44
src/Predicate/AllOfPredicate.php
Normal file
44
src/Predicate/AllOfPredicate.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright 2018 Kacper Donat
|
||||||
|
*
|
||||||
|
* @author Kacper "Kadet" Donat <kacper@kadet.net>
|
||||||
|
*
|
||||||
|
* Full license available in separate LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Kadet\Functional\Predicate;
|
||||||
|
|
||||||
|
|
||||||
|
use Kadet\Functional\Predicate;
|
||||||
|
|
||||||
|
class AllOfPredicate extends AbstractPredicate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Array of predicates to check if all are satisfied.
|
||||||
|
* @var \Kadet\Functional\Predicate[]
|
||||||
|
*/
|
||||||
|
private $predicates = [];
|
||||||
|
|
||||||
|
public function __construct(Predicate ...$predicates)
|
||||||
|
{
|
||||||
|
$this->predicates = $predicates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function and(...$predicate): Predicate
|
||||||
|
{
|
||||||
|
$predicate = array_merge($this->predicates, $predicate);
|
||||||
|
return parent::and($predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(...$args): bool
|
||||||
|
{
|
||||||
|
foreach ($this->predicates as $predicate) {
|
||||||
|
if (!$predicate(...$args)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
45
src/Predicate/AnyOfPredicate.php
Normal file
45
src/Predicate/AnyOfPredicate.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright 2018 Kacper Donat
|
||||||
|
*
|
||||||
|
* @author Kacper "Kadet" Donat <kacper@kadet.net>
|
||||||
|
*
|
||||||
|
* Full license available in separate LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Kadet\Functional\Predicate;
|
||||||
|
|
||||||
|
|
||||||
|
use Kadet\Functional\Predicate;
|
||||||
|
|
||||||
|
class AnyOfPredicate extends AbstractPredicate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Array of predicates to check if all are satisfied.
|
||||||
|
* @var \Kadet\Functional\Predicate[]
|
||||||
|
*/
|
||||||
|
private $predicates = [];
|
||||||
|
|
||||||
|
public function __construct(Predicate ...$predicates)
|
||||||
|
{
|
||||||
|
$this->predicates = $predicates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function or(...$predicate): Predicate
|
||||||
|
{
|
||||||
|
$predicate = array_merge($this->predicates, $predicate);
|
||||||
|
return parent::or($predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function __invoke(...$args): bool
|
||||||
|
{
|
||||||
|
foreach ($this->predicates as $predicate) {
|
||||||
|
if ($predicate(...$args)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
34
src/Predicate/ClosurePredicate.php
Normal file
34
src/Predicate/ClosurePredicate.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright 2018 Kacper Donat
|
||||||
|
*
|
||||||
|
* @author Kacper "Kadet" Donat <kacper@kadet.net>
|
||||||
|
*
|
||||||
|
* Full license available in separate LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Kadet\Functional\Predicate;
|
||||||
|
|
||||||
|
|
||||||
|
class ClosurePredicate extends AbstractPredicate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Closure
|
||||||
|
*/
|
||||||
|
private $closure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClosurePredicate constructor.
|
||||||
|
*
|
||||||
|
* @param \Closure $closure
|
||||||
|
*/
|
||||||
|
public function __construct(\Closure $closure)
|
||||||
|
{
|
||||||
|
$this->closure = $closure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(...$args): bool
|
||||||
|
{
|
||||||
|
return ($this->closure)(...$args);
|
||||||
|
}
|
||||||
|
}
|
38
src/Predicate/NegatedPredicate.php
Normal file
38
src/Predicate/NegatedPredicate.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright 2018 Kacper Donat
|
||||||
|
*
|
||||||
|
* @author Kacper "Kadet" Donat <kacper@kadet.net>
|
||||||
|
*
|
||||||
|
* Full license available in separate LICENSE file
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Kadet\Functional\Predicate;
|
||||||
|
|
||||||
|
|
||||||
|
use Kadet\Functional\Predicate;
|
||||||
|
|
||||||
|
class NegatedPredicate extends AbstractPredicate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Predicate to be negated.
|
||||||
|
* @var \Kadet\Functional\Predicate
|
||||||
|
*/
|
||||||
|
private $negated;
|
||||||
|
|
||||||
|
public function __construct(Predicate $predicate)
|
||||||
|
{
|
||||||
|
$this->negated = $predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function not(): Predicate
|
||||||
|
{
|
||||||
|
// negation of negations is plain value
|
||||||
|
return $this->negated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(...$args): bool
|
||||||
|
{
|
||||||
|
return !($this->negated)(...$args);
|
||||||
|
}
|
||||||
|
}
|
26
src/functions.php
Normal file
26
src/functions.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kadet\Functional;
|
||||||
|
|
||||||
|
use Kadet\Functional\Predicate\ClosurePredicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $predicate
|
||||||
|
*
|
||||||
|
* @return \Kadet\Functional\Predicate
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
function predicate($predicate): Predicate
|
||||||
|
{
|
||||||
|
if ($predicate instanceof Predicate) {
|
||||||
|
return $predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_callable($predicate)) {
|
||||||
|
return new ClosurePredicate(\Closure::fromCallable($predicate));
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo better exception
|
||||||
|
throw new \Exception();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user