diff --git a/src/Plugin/Filtering/Builder/Reject.php b/src/Plugin/Filtering/Builder/Reject.php index a59b9257..e62d069b 100644 --- a/src/Plugin/Filtering/Builder/Reject.php +++ b/src/Plugin/Filtering/Builder/Reject.php @@ -6,6 +6,8 @@ use Kiboko\Component\Bucket\AcceptanceResultBucket; use Kiboko\Component\Bucket\RejectionResultBucket; +use Kiboko\Component\Bucket\RejectionWithReasonResultBucket; +use Kiboko\Component\Satellite\Plugin\Filtering\DTO\Exclusion; use Kiboko\Contract\Configurator\StepBuilderInterface; use Kiboko\Contract\Pipeline\TransformerInterface; use PhpParser\Builder; @@ -17,11 +19,9 @@ final class Reject implements StepBuilderInterface private ?Node\Expr $rejection = null; private ?Node\Expr $state = null; private ?Node\Expr $rejection_serializer = null; - /** @var list */ + /** @var list */ private array $exclusions = []; - public function __construct() {} - public function withLogger(Node\Expr $logger): self { $this->logger = $logger; @@ -50,53 +50,46 @@ public function withRejectionSerializer(Node\Expr $rejection_serializer): self return $this; } - public function withExclusions(Node\Expr ...$exclusions): self + public function withExclusions(Exclusion ...$exclusions): self { array_push($this->exclusions, ...$exclusions); return $this; } - private function buildExclusions(Node\Expr ...$exclusions): Node\Expr + private function buildExclusions(Exclusion ...$exclusions): array { - if (\count($exclusions) > 3) { - $length = \count($exclusions); - $middle = (int) floor($length / 2); - $left = \array_slice($exclusions, 0, $middle); - $right = \array_slice($exclusions, $middle, $length); - - return new Node\Expr\BinaryOp\BooleanAnd( - $this->buildExclusions(...$left), - $this->buildExclusions(...$right), - ); - } - - if (\count($exclusions) > 2) { - $right = array_shift($exclusions); - - return new Node\Expr\BinaryOp\BooleanAnd( - $this->buildExclusions(...$exclusions), - $right, - ); - } - - if (\count($exclusions) > 1) { - $left = array_pop($exclusions); - $right = array_pop($exclusions); - - return new Node\Expr\BinaryOp\BooleanAnd( - $left, - $right, + $statements = []; + foreach ($exclusions as $exclusion) { + $statements[] = new Node\Stmt\If_( + $exclusion->when, + [ + 'stmts' => [ + new Node\Stmt\Expression( + new Node\Expr\Assign( + new Node\Expr\Variable('input'), + new Node\Expr\Yield_( + new Node\Expr\New_( + $exclusion->reason ? new Node\Name\FullyQualified(RejectionWithReasonResultBucket::class) : new Node\Name\FullyQualified(RejectionResultBucket::class), + [ + null !== $this->rejection_serializer ? new Node\Arg($this->rejection_serializer) : new Node\Arg(new Node\Expr\Variable('input')), + $exclusion->reason ? new Node\Arg($exclusion->reason) : new Node\Arg( + new Node\Expr\ConstFetch( + new Node\Name(null) + ), + ), + ] + ), + ), + ), + ), + new Node\Stmt\Continue_(), + ], + ] ); } - if (\count($exclusions) > 0) { - return array_pop($exclusions); - } - - return new Node\Expr\ConstFetch( - new Node\Name('false'), - ); + return $statements; } public function getNode(): Node @@ -122,27 +115,7 @@ class: new Node\Stmt\Class_(null, [ new Node\Name('true'), ), [ - new Node\Stmt\If_( - $this->buildExclusions(...$this->exclusions), - [ - 'stmts' => [ - new Node\Stmt\Expression( - new Node\Expr\Assign( - new Node\Expr\Variable('input'), - new Node\Expr\Yield_( - new Node\Expr\New_( - new Node\Name\FullyQualified(RejectionResultBucket::class), - [ - null !== $this->rejection_serializer ? new Node\Arg($this->rejection_serializer) : new Node\Arg(new Node\Expr\Variable('input')), - ] - ), - ), - ), - ), - new Node\Stmt\Continue_(), - ], - ] - ), + ...$this->buildExclusions(...$this->exclusions), new Node\Stmt\Expression( new Node\Expr\Assign( new Node\Expr\Variable('input'), diff --git a/src/Plugin/Filtering/Configuration/Reject.php b/src/Plugin/Filtering/Configuration/Reject.php index d08f422a..386771bb 100644 --- a/src/Plugin/Filtering/Configuration/Reject.php +++ b/src/Plugin/Filtering/Configuration/Reject.php @@ -28,6 +28,12 @@ public function getConfigTreeBuilder(): TreeBuilder ->then(asExpression()) ->end() ->end() + ->scalarNode('reason') + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ->end() ->scalarNode('rejection_serializer') ->cannotBeEmpty() ->validate() diff --git a/src/Plugin/Filtering/DTO/Exclusion.php b/src/Plugin/Filtering/DTO/Exclusion.php new file mode 100644 index 00000000..7dfc1af5 --- /dev/null +++ b/src/Plugin/Filtering/DTO/Exclusion.php @@ -0,0 +1,15 @@ +withExclusions( - compileExpression($interpreter, $condition['when']) + new Filtering\DTO\Exclusion( + compileExpression($interpreter, $condition['when']), + compileValueWhenExpression($interpreter, $condition['reason']) ?: null, + ), ); if (\array_key_exists('rejection_serializer', $condition)) { $builder->withRejectionSerializer(compileExpression($interpreter, $condition['rejection_serializer']));