Lines 100.00% 19 / 19
Functions and Methods 100.00% 6 / 6
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
ConsoleKernel 100.00% 19 / 19 100.00% 6 / 6 7 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 createApplication 100.00% 4 / 4 100.00% 1 / 1 1
 compileContainer 100.00% 1 / 1 100.00% 1 / 1 1
 buildSyntheticServicesForProject 100.00% 5 / 5 100.00% 1 / 1 1
 buildNamedArgumentsForProject 100.00% 3 / 3 100.00% 1 / 1 1
 detectInstalledVersion 100.00% 5 / 5 100.00% 1 / 1 2
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Runtime\Kernel;
6
7use Composer\InstalledVersions;
8use Stewart\Runtime\Config\ProjectRoot;
9use Stewart\Runtime\Config\Psr4Map;
10use Stewart\Runtime\Console\StewartApplication;
11use Stewart\Runtime\Container\TypedContainer;
12use Stewart\Runtime\Model\StewartVersion;
13use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
14
15final readonly class ConsoleKernel
16{
17    private const string APPS_DIRECTORY = '/apps';
18
19    private const string SERVICES_FILE = '/services.php';
20
21    private const string RUNTIME_PACKAGE = 'stewart-php/runtime';
22
23    private const string UNKNOWN_VERSION = 'unknown';
24
25    /** @param array<string, array<int, string>> $psr4 */
26    public function __construct(
27        private string $projectDir,
28        private array $psr4,
29        private SyntheticServices $overrides = new SyntheticServices(),
30    ) {}
31
32    public function createApplication(): StewartApplication
33    {
34        $container = $this->compileContainer();
35
36        $application = new StewartApplication($this->detectInstalledVersion()->value);
37        $application->setCommandLoader($container->resolveService(CommandLoaderInterface::class, 'console.command_loader'));
38
39        return $application;
40    }
41
42    public function compileContainer(): TypedContainer
43    {
44        return new ProfileCompiler()->compileProfileContainer(ContainerProfile::Console, $this->buildSyntheticServicesForProject(), $this->buildNamedArgumentsForProject());
45    }
46
47    private function buildSyntheticServicesForProject(): SyntheticServices
48    {
49        return new SyntheticServices()
50            ->withService(ProjectRoot::class, new ProjectRoot($this->projectDir))
51            ->withService(Psr4Map::class, new Psr4Map($this->psr4))
52            ->withService(StewartVersion::class, $this->detectInstalledVersion())
53            ->withOverrides($this->overrides);
54    }
55
56    private function buildNamedArgumentsForProject(): NamedArguments
57    {
58        return new NamedArguments()
59            ->withArgument('appsDirectory', $this->projectDir . self::APPS_DIRECTORY)
60            ->withArgument('userServicesFile', $this->projectDir . self::SERVICES_FILE);
61    }
62
63    private function detectInstalledVersion(): StewartVersion
64    {
65        return new StewartVersion(
66            InstalledVersions::isInstalled(self::RUNTIME_PACKAGE)
67                ? InstalledVersions::getPrettyVersion(self::RUNTIME_PACKAGE) ?? self::UNKNOWN_VERSION
68                : self::UNKNOWN_VERSION,
69        );
70    }
71}