-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Condition interface, abstract and decorators.
- Loading branch information
Showing
14 changed files
with
762 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,13 +9,29 @@ | |
"email": "[email protected]" | ||
} | ||
], | ||
"minimum-stability": "dev", | ||
"require": { | ||
"php": ">=8.0" | ||
}, | ||
"require-dev": { | ||
"phpunit/phpunit": "11.5.x-dev" | ||
"phpunit/phpunit": "^9.0", | ||
"squizlabs/php_codesniffer": "^3.0" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Ananke\\": "src/" | ||
} | ||
}, | ||
"autoload-dev": { | ||
"psr-4": { | ||
"Ananke\\Tests\\": "tests/" | ||
} | ||
}, | ||
"scripts": { | ||
"test": "phpunit", | ||
"cs-check": "phpcs", | ||
"cs-fix": "phpcbf" | ||
}, | ||
"config": { | ||
"sort-packages": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
|
||
namespace Ananke\Conditions; | ||
|
||
/** | ||
* Base class for conditions providing common functionality. | ||
*/ | ||
abstract class AbstractCondition implements ConditionInterface | ||
{ | ||
protected string $name; | ||
|
||
/** | ||
* @param string $name Unique identifier for this condition | ||
*/ | ||
public function __construct(string $name) | ||
{ | ||
$this->name = $name; | ||
} | ||
|
||
public function getName(): string | ||
{ | ||
return $this->name; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
namespace Ananke\Conditions; | ||
|
||
/** | ||
* Decorator that combines multiple conditions with AND logic. | ||
*/ | ||
class AndCondition extends AbstractCondition | ||
{ | ||
/** @var ConditionInterface[] */ | ||
private array $conditions; | ||
|
||
/** | ||
* @param ConditionInterface[] $conditions List of conditions to combine | ||
*/ | ||
public function __construct(array $conditions) | ||
{ | ||
$names = array_map(fn($c) => $c->getName(), $conditions); | ||
parent::__construct('and_' . implode('_', $names)); | ||
$this->conditions = $conditions; | ||
} | ||
|
||
public function evaluate(): bool | ||
{ | ||
foreach ($this->conditions as $condition) { | ||
if (!$condition->evaluate()) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
namespace Ananke\Conditions; | ||
|
||
/** | ||
* Decorator that caches another condition's result for a specified duration. | ||
*/ | ||
class CachedCondition extends AbstractCondition | ||
{ | ||
private ConditionInterface $condition; | ||
private ?bool $cachedResult = null; | ||
private ?int $cachedAt = null; | ||
private int $ttl; | ||
|
||
/** | ||
* @param ConditionInterface $condition The condition to cache | ||
* @param int $ttl Time to live in seconds | ||
*/ | ||
public function __construct(ConditionInterface $condition, int $ttl) | ||
{ | ||
parent::__construct("cached_{$condition->getName()}"); | ||
$this->condition = $condition; | ||
$this->ttl = $ttl; | ||
} | ||
|
||
public function evaluate(): bool | ||
{ | ||
$now = time(); | ||
|
||
// If we have a cached result and it hasn't expired | ||
if ($this->cachedResult !== null && | ||
$this->cachedAt !== null && | ||
$now - $this->cachedAt < $this->ttl | ||
) { | ||
return $this->cachedResult; | ||
} | ||
|
||
// Evaluate and cache the result | ||
$this->cachedResult = $this->condition->evaluate(); | ||
$this->cachedAt = $now; | ||
|
||
return $this->cachedResult; | ||
} | ||
|
||
/** | ||
* Clear the cached result. | ||
*/ | ||
public function clearCache(): void | ||
{ | ||
$this->cachedResult = null; | ||
$this->cachedAt = null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
namespace Ananke\Conditions; | ||
|
||
/** | ||
* Basic condition implementation that wraps a callable. | ||
*/ | ||
class CallableCondition implements ConditionInterface | ||
{ | ||
private string $name; | ||
private \Closure $validator; | ||
|
||
/** | ||
* @param string $name Unique identifier for this condition | ||
* @param callable $validator Function that returns bool when evaluated | ||
*/ | ||
public function __construct(string $name, callable $validator) | ||
{ | ||
$this->name = $name; | ||
$this->validator = \Closure::fromCallable($validator); | ||
} | ||
|
||
public function evaluate(): bool | ||
{ | ||
return ($this->validator)(); | ||
} | ||
|
||
public function getName(): string | ||
{ | ||
return $this->name; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?php | ||
|
||
namespace Ananke\Conditions; | ||
|
||
/** | ||
* Interface for service conditions. | ||
* | ||
* Conditions are used to determine whether a service can be instantiated. | ||
* They can be simple callables or complex compositions using decorators. | ||
*/ | ||
interface ConditionInterface | ||
{ | ||
/** | ||
* Evaluate the condition. | ||
* | ||
* @return bool True if the condition is met, false otherwise | ||
*/ | ||
public function evaluate(): bool; | ||
|
||
/** | ||
* Get a unique identifier for this condition. | ||
* | ||
* @return string Condition identifier | ||
*/ | ||
public function getName(): string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php | ||
|
||
namespace Ananke\Conditions; | ||
|
||
/** | ||
* Decorator that negates another condition's result. | ||
*/ | ||
class NotCondition extends AbstractCondition | ||
{ | ||
private ConditionInterface $condition; | ||
|
||
/** | ||
* @param ConditionInterface $condition The condition to negate | ||
*/ | ||
public function __construct(ConditionInterface $condition) | ||
{ | ||
parent::__construct("not_{$condition->getName()}"); | ||
$this->condition = $condition; | ||
} | ||
|
||
public function evaluate(): bool | ||
{ | ||
return !$this->condition->evaluate(); | ||
} | ||
} |
Oops, something went wrong.