Lines 100.00% 16 / 16
Functions and Methods 100.00% 5 / 5
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
ControlCommand 100.00% 16 / 16 100.00% 5 / 5 6 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 configure 100.00% 5 / 5 100.00% 1 / 1 1
 resolveControlTarget 100.00% 6 / 6 100.00% 1 / 1 1
 writeCommandResult 100.00% 3 / 3 100.00% 1 / 1 2
 parseTimeoutOption 100.00% 1 / 1 100.00% 1 / 1 1
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Runtime\Console;
6
7use Stewart\Contracts\Exception\StewartException;
8use Stewart\Contracts\Time\Duration;
9use Stewart\Runtime\Config\ConfigLoader;
10use Stewart\Runtime\Config\ControlConfig;
11use Stewart\Runtime\Control\Client\ControlTarget;
12use Stewart\Runtime\Control\Client\ControlTargetResolver;
13use Stewart\Runtime\Control\Protocol\Frame\CommandResult;
14use Symfony\Component\Console\Input\InputInterface;
15use Symfony\Component\Console\Input\InputOption;
16use Symfony\Component\Console\Output\OutputInterface;
17
18abstract class ControlCommand extends StewartCommand
19{
20    private const string DEFAULT_TIMEOUT = '5s';
21
22    public function __construct(
23        private readonly ConfigLoader $config,
24        private readonly ControlTargetResolver $targets,
25    ) {
26        parent::__construct();
27    }
28
29    protected function configure(): void
30    {
31        parent::configure();
32        $this
33            ->addOption('address', null, InputOption::VALUE_REQUIRED, 'Where the daemon listens, such as unix://var/run/stewart.sock or tcp://host:port; defaults to control.listen')
34            ->addOption('token', null, InputOption::VALUE_REQUIRED, 'The control token; defaults to control.token, usually STEWART_CONTROL__TOKEN')
35            ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'How long to wait for the daemon, like 5s', self::DEFAULT_TIMEOUT);
36    }
37
38    /** @throws StewartException */
39    protected function resolveControlTarget(InputInterface $input): ControlTarget
40    {
41        $path = $this->findConfigOption($input);
42
43        return $this->targets->resolveTarget(
44            $this->nonEmptyStringOption($input, 'address'),
45            $this->nonEmptyStringOption($input, 'token'),
46            fn(): ControlConfig => $this->config->loadConfig($path)->control,
47        );
48    }
49
50    protected function writeCommandResult(OutputInterface $output, CommandResult $result): void
51    {
52        $output->writeln($result->message);
53
54        if ($result->warning !== null) {
55            $this->writeNotice($output, $result->warning);
56        }
57    }
58
59    /** @throws StewartException */
60    protected function parseTimeoutOption(InputInterface $input): Duration
61    {
62        return Duration::parse($this->nonEmptyStringOption($input, 'timeout') ?? self::DEFAULT_TIMEOUT);
63    }
64}