ApplicationFactory   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 71
Duplicated Lines 0 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
eloc 35
dl 0
loc 71
rs 10
c 3
b 1
f 1
wmc 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getControllerConstructorArguments() 0 10 2
A getArgument() 0 19 5
A makeApplication() 0 33 3
1
<?php
2
declare(strict_types=1);
3
4
namespace Selami\Console;
5
6
use Symfony\Component\Console\Application;
7
use Psr\Container\ContainerInterface;
8
use Symfony\Component\Console\Command\Command;
9
use Selami\Stdlib\Resolver;
10
use ReflectionClass;
11
use Selami\Console\Exception\DependencyNotFoundException;
12
use Selami\Stdlib\Exception\ClassOrMethodCouldNotBeFound;
13
14
class ApplicationFactory
15
{
16
    public static function makeApplication(
17
        ContainerInterface $container,
18
        string $name = 'ConsoleApp',
19
        string $version = '0.0.1'
20
    ) : Application {
21
        /**
22
         * @var array $commands
23
         */
24
        $commands = $container->get('commands');
25
        $cli = new Application($name, $version);
26
        $consoleApplicationArguments = [
27
            'name' => $name,
28
            'version' => $version
29
        ];
30
        foreach ($commands as $command) {
31
            $controllerConstructorArguments = self::getControllerConstructorArguments($command);
32
            $arguments = [];
33
            foreach ($controllerConstructorArguments as $argumentName => $argumentType) {
34
                $arguments[] = self::getArgument(
35
                    $container,
36
                    $consoleApplicationArguments,
37
                    $argumentName,
38
                    $argumentType
39
                );
40
            }
41
            $reflectionClass = new ReflectionClass($command);
42
            /**
43
             * @var Command $autoWiredCommand
44
             */
45
            $autoWiredCommand = $reflectionClass->newInstanceArgs($arguments);
46
            $cli->add($autoWiredCommand);
47
        }
48
        return $cli;
49
    }
50
51
    private static function getControllerConstructorArguments($command): ?array
52
    {
53
        try {
54
            return Resolver::getParameterHints($command, '__construct');
55
        } catch (ClassOrMethodCouldNotBeFound $e) {
56
            throw new DependencyNotFoundException(
57
                sprintf(
58
                    '%s when calling command: %s',
59
                    $e->getMessage(),
60
                    $command
61
                )
62
            );
63
        }
64
    }
65
66
    private static function getArgument(
67
        ContainerInterface $container,
68
        array $consoleApplicationArguments,
69
        string $argumentName,
70
        string $argumentType
71
    ) {
72
73
        if (array_key_exists($argumentName, $consoleApplicationArguments)) {
74
            return $consoleApplicationArguments[$argumentName];
75
        }
76
        if ($argumentType === Resolver::ARRAY && $container->has($argumentName) === false) {
77
            throw new DependencyNotFoundException(
78
                sprintf('Container does not have an item for array: %s', $argumentName)
79
            );
80
        }
81
        if ($argumentType === Resolver::ARRAY) {
82
            return $container->get($argumentName);
83
        }
84
        return $container->get($argumentType);
85
    }
86
}
87