<?php
/*
* This file is part of Chevere.
*
* (c) Rodolfo Berrios <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chevere\Workflow;
use Chevere\DataStructure\Interfaces\VectorInterface;
use Chevere\DataStructure\Map;
use Chevere\DataStructure\Traits\MapTrait;
use Chevere\DataStructure\Vector;
use Chevere\Message\Interfaces\MessageInterface;
use Chevere\Parameter\Arguments;
use Chevere\Parameter\Interfaces\ArgumentsInterface;
use Chevere\Parameter\Interfaces\CastInterface;
use Chevere\Workflow\Interfaces\RunInterface;
use Chevere\Workflow\Interfaces\WorkflowInterface;
use OverflowException;
use function Chevere\Message\message;
use function Chevere\Parameter\cast;
final class Run implements RunInterface
{
/**
* @template-use MapTrait<CastInterface>
*/
use MapTrait;
private string $uuid;
private ArgumentsInterface $arguments;
/**
* Skipped jobs.
*
* @var VectorInterface<string>
*/
private VectorInterface $skip;
/**
* @param mixed ...$variable Variables matching workflow parameters
*/
public function __construct(
private WorkflowInterface $workflow,
mixed ...$variable
) {
$this->uuid = uuidv4();
$this->arguments = new Arguments(
$workflow->parameters(),
$variable
);
$this->map = new Map();
$this->skip = new Vector();
}
public function uuid(): string
{
return $this->uuid;
}
public function workflow(): WorkflowInterface
{
return $this->workflow;
}
public function arguments(): ArgumentsInterface
{
return $this->arguments;
}
public function skip(): VectorInterface
{
return $this->skip;
}
public function withResponse(string $job, CastInterface $response): RunInterface
{
$this->assertNoSkipOverflow($job, message('Job %job% is skipped'));
$new = clone $this;
$new->workflow->jobs()->get($job);
$new->workflow->getJobResponseParameter($job)->__invoke($response->mixed());
$new->map = $new->map->withPut($job, $response);
return $new;
}
public function withSkip(string ...$job): RunInterface
{
$new = clone $this;
foreach ($job as $item) {
$new->workflow->jobs()->get($item);
$new->assertNoSkipOverflow($item, message('Job %job% already skipped'));
$new->skip = $new->skip->withPush($item);
}
return $new;
}
public function response(string $job, string|int ...$key): CastInterface
{
return cast($this->map->get($job)->mixed(), ...$key);
}
/**
* @codeCoverageIgnore
*/
public function getReturn(string $job): CastInterface
{
return $this->response($job);
}
private function assertNoSkipOverflow(string $job, MessageInterface $message): void
{
if ($this->skip->contains($job)) {
throw new OverflowException(
strtr($message->__toString(), [
'%job%' => $job,
])
);
}
}
}
|