Passed
Push — master ( 1995be...2b4444 )
by Dmitriy
07:56 queued 04:33
created

CommandController   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 20
eloc 66
c 1
b 0
f 0
dl 0
loc 119
ccs 0
cts 76
cp 0
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getComposerScripts() 0 14 5
A index() 0 32 5
B run() 0 61 9
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Debug\Api\Controller;
6
7
use InvalidArgumentException;
8
use Psr\Container\ContainerInterface;
9
use Psr\Http\Message\ResponseInterface;
10
use Psr\Http\Message\ServerRequestInterface;
11
use Yiisoft\Aliases\Aliases;
12
use Yiisoft\Config\ConfigInterface;
13
use Yiisoft\DataResponse\DataResponseFactoryInterface;
14
use Yiisoft\Yii\Debug\Api\Inspector\Command\BashCommand;
15
use Yiisoft\Yii\Debug\Api\Inspector\CommandInterface;
16
17
class CommandController
18
{
19
    public function __construct(
20
        private DataResponseFactoryInterface $responseFactory,
21
    ) {
22
    }
23
24
    public function index(ConfigInterface $config, Aliases $aliases): ResponseInterface
25
    {
26
        $params = $config->get('params');
27
        $configCommandMap = $params['yiisoft/yii-debug-api']['inspector']['commandMap'] ?? [];
28
29
        $result = [];
30
        foreach ($configCommandMap as $groupName => $commands) {
31
            foreach ($commands as $name => $command) {
32
                if (!is_subclass_of($command, CommandInterface::class)) {
33
                    continue;
34
                }
35
                $result[] = [
36
                    'name' => $name,
37
                    'title' => $command::getTitle(),
38
                    'group' => $groupName,
39
                    'description' => $command::getDescription(),
40
                ];
41
            }
42
        }
43
44
        $composerScripts = $this->getComposerScripts($aliases);
45
        foreach ($composerScripts as $scriptName => $commands) {
46
            $commandName = "composer/{$scriptName}";
47
            $result[] = [
48
                'name' => $commandName,
49
                'title' => $scriptName,
50
                'group' => 'composer',
51
                'description' => implode("\n", $commands),
52
            ];
53
        }
54
55
        return $this->responseFactory->createResponse($result);
56
    }
57
58
    public function run(
59
        ServerRequestInterface $request,
60
        ContainerInterface $container,
61
        ConfigInterface $config,
62
        Aliases $aliases,
63
    ): ResponseInterface {
64
        $params = $config->get('params');
65
        $commandMap = $params['yiisoft/yii-debug-api']['inspector']['commandMap'] ?? [];
66
67
        /**
68
         * @var array<string, class-string<CommandInterface>> $commandList
69
         */
70
        $commandList = [];
71
        foreach ($commandMap as $commands) {
72
            foreach ($commands as $name => $command) {
73
                if (!is_subclass_of($command, CommandInterface::class)) {
74
                    continue;
75
                }
76
                $commandList[$name] = $command;
77
            }
78
        }
79
        $composerScripts = $this->getComposerScripts($aliases);
80
        foreach ($composerScripts as $scriptName => $commands) {
81
            $commandName = "composer/{$scriptName}";
82
            $commandList[$commandName] = ['composer', $scriptName];
83
        }
84
85
        $request = $request->getQueryParams();
86
        $commandName = $request['command'] ?? null;
87
88
        if ($commandName === null) {
89
            throw new InvalidArgumentException(
90
                sprintf(
91
                    'Command must not be null. Available commands: "%s".',
92
                    implode('", "', $commandList)
93
                )
94
            );
95
        }
96
97
        if (!array_key_exists($commandName, $commandList)) {
98
            throw new InvalidArgumentException(
99
                sprintf(
100
                    'Unknown command "%s". Available commands: "%s".',
101
                    $commandName,
102
                    implode('", "', $commandList)
103
                )
104
            );
105
        }
106
107
        $commandClass = $commandList[$commandName];
108
        if (is_string($commandClass) && $container->has($commandClass)) {
109
            $command = $container->get($commandClass);
110
        } else {
111
            $command = new BashCommand($aliases, (array)$commandClass);
112
        }
113
        $result = $command->run();
114
115
        return $this->responseFactory->createResponse([
116
            'status' => $result->getStatus(),
117
            'result' => $result->getResult(),
118
            'error' => $result->getErrors(),
119
        ]);
120
    }
121
122
    private function getComposerScripts(Aliases $aliases): array
123
    {
124
        $result = [];
125
        $composerJsonPath = $aliases->get('@root/composer.json');
126
        if (file_exists($composerJsonPath)) {
127
            $composerJsonCommands = json_decode(file_get_contents($composerJsonPath), true, 512, JSON_THROW_ON_ERROR);
128
            if (is_array($composerJsonCommands) && isset($composerJsonCommands['scripts'])) {
129
                $scripts = $composerJsonCommands['scripts'];
130
                foreach ($scripts as $name => $script) {
131
                    $result[$name] = (array) $script;
132
                }
133
            }
134
        }
135
        return $result;
136
    }
137
}
138