Passed
Branch master (372b2a)
by Filipe
01:32
created

ConsoleCommandLoader::get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 7
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
/**
4
 * This file is part of web-stack
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Slick\WebStack\Infrastructure\Console;
13
14
use Exception;
15
use Psr\Container\ContainerExceptionInterface;
16
use Psr\Container\NotFoundExceptionInterface;
17
use ReflectionClass;
18
use ReflectionException;
19
use Slick\Di\ContainerInterface;
20
use Slick\WebStack\Infrastructure\Console\ConsoleCommandLoader\ConsoleCommandList;
21
use Symfony\Component\Console\Command\Command;
22
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
23
use Symfony\Component\Console\Exception\CommandNotFoundException;
24
25
/**
26
 * ConsoleCommandLoader
27
 *
28
 * @package Slick\WebStack\Infrastructure\Console
29
 */
30
final class ConsoleCommandLoader implements CommandLoaderInterface
31
{
32
    /**
33
     * @var ConsoleCommandList
34
     */
35
    private ConsoleCommandList $commands;
36
37
    public function __construct(
38
        private readonly ContainerInterface $container,
39
        private readonly string $sourcePath
40
    ) {
41
        $this->commands = new ConsoleCommandList($this->sourcePath);
42
    }
43
44
    /**
45
     * @inheritDoc
46
     * @throws ReflectionException
47
     * @throws ContainerExceptionInterface
48
     * @throws NotFoundExceptionInterface
49
     */
50
    public function get(string $name): Command
51
    {
52
        if ($this->has($name)) {
53
            return $this->createCommand($name);
54
        }
55
56
        throw new CommandNotFoundException("Command '$name' not found.");
57
    }
58
59
    /**
60
     * @inheritDoc
61
     */
62
    public function has(string $name): bool
63
    {
64
        return $this->commands->offsetExists($name);
65
    }
66
67
    /**
68
     * @inheritDoc
69
     * @throws Exception
70
     */
71
    public function getNames(): array
72
    {
73
        return array_keys($this->commands->getIterator()->getArrayCopy());
74
    }
75
76
    /**
77
     * Creates a command object based on the provided command name.
78
     *
79
     * @param string $name The command name.
80
     * @return Command The created command object.
81
     * @throws ReflectionException When reflection is unable to process the command class.
82
     * @throws ContainerExceptionInterface
83
     * @throws NotFoundExceptionInterface
84
     */
85
    public function createCommand(string $name): Command
86
    {
87
        /** @var class-string<Command> $commandClassName */
88
        $commandClassName = $this->commands[$name];
89
        $reflection = new ReflectionClass($commandClassName);
90
        $constructor = $reflection->getConstructor();
91
        $arguments = [null];
92
        $hasNameArgument = false;
93
94
        if ($constructor) {
95
            $ags = $constructor->getParameters();
96
            $hasNameArgument = isset($ags[0]) && $ags[0]->getName() === 'name';
97
        }
98
99
        return $hasNameArgument
100
            ? $this->container->make($commandClassName, ...$arguments)
101
            : $this->container->get($commandClassName);
102
    }
103
}
104