Lines 100.00% 18 / 18
Functions and Methods 100.00% 3 / 3
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
CheckCommand 100.00% 18 / 18 100.00% 3 / 3 7 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 execute 100.00% 15 / 15 100.00% 1 / 1 5
 describeUnloadableFile 100.00% 2 / 2 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\Runtime\App\AppCatalogResolver;
9use Stewart\Runtime\App\AppDiscovery;
10use Stewart\Runtime\App\UnloadableAppFile;
11use Stewart\Runtime\Config\ConfigLoader;
12use Symfony\Component\Console\Attribute\AsCommand;
13use Symfony\Component\Console\Command\Command;
14use Symfony\Component\Console\Input\InputInterface;
15use Symfony\Component\Console\Output\ConsoleOutputInterface;
16use Symfony\Component\Console\Output\OutputInterface;
17
18#[AsCommand(name: self::NAME, description: 'Check that the configuration loads and every automation file loads')]
19final class CheckCommand extends StewartCommand
20{
21    public const string NAME = 'check';
22
23    public function __construct(
24        private readonly ConfigLoader $config,
25        private readonly AppDiscovery $discovery,
26        private readonly AppCatalogResolver $catalogs,
27    ) {
28        parent::__construct();
29    }
30
31    protected function execute(InputInterface $input, OutputInterface $output): int
32    {
33        $errors = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output;
34
35        try {
36            $config = $this->config->loadConfig($this->findConfigOption($input));
37            $config->requireHomeAssistant();
38            $discovered = $this->discovery->discover();
39            $apps = $this->catalogs->resolveCatalog($discovered, $config->apps, $config->workers);
40        } catch (StewartException $e) {
41            $errors->writeln('<error>' . $e->getMessage() . '</error>');
42
43            return Command::FAILURE;
44        }
45
46        if (!$discovered->unloadable->isEmpty()) {
47            foreach ($discovered->unloadable as $file) {
48                $errors->writeln('<error>' . $this->describeUnloadableFile($file) . '</error>');
49            }
50
51            return Command::FAILURE;
52        }
53
54        $this->writeMissingConfigFileNotice($output, $this->config->findMissingDefaultFile($this->findConfigOption($input)));
55        $output->writeln(\sprintf('Configuration and %d automations load; %d enabled.', $discovered->apps->count(), $apps->enabled->count()));
56
57        return Command::SUCCESS;
58    }
59
60    private function describeUnloadableFile(UnloadableAppFile $file): string
61    {
62        $cause = str_replace(["\r", "\n"], ' ', $file->cause->getMessage());
63
64        return \sprintf('%s failed to load: %s', $file->path, $cause);
65    }
66}