CommandCollector::getSummary()   A
last analyzed

Complexity

Conditions 6
Paths 10

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 10
nop 0
dl 0
loc 28
rs 9.0777
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Debug\Collector\Console;
6
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Event\ConsoleErrorEvent;
9
use Symfony\Component\Console\Event\ConsoleEvent;
10
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use Yiisoft\Yii\Console\Output\ConsoleBufferedOutput;
14
use Yiisoft\Yii\Debug\Collector\CollectorTrait;
15
use Yiisoft\Yii\Debug\Collector\SummaryCollectorInterface;
16
use Yiisoft\Yii\Debug\Collector\TimelineCollector;
17
18
final class CommandCollector implements SummaryCollectorInterface
19
{
20
    use CollectorTrait;
21
22
    /**
23
     * Let -1 mean that it was not set during the process.
24
     */
25
    private const UNDEFINED_EXIT_CODE = -1;
26
    private array $commands = [];
27
28
    public function __construct(
29
        private readonly TimelineCollector $timelineCollector
30
    ) {
31
    }
32
33
    public function getCollected(): array
34
    {
35
        return $this->commands;
36
    }
37
38
    public function collect(ConsoleEvent|ConsoleErrorEvent|ConsoleTerminateEvent $event): void
39
    {
40
        if (!$this->isActive()) {
41
            return;
42
        }
43
44
        $this->timelineCollector->collect($this, spl_object_id($event));
45
46
        $command = $event->getCommand();
47
48
        if ($event instanceof ConsoleErrorEvent) {
49
            $this->commands[$event::class] = [
50
                'name' => $event->getInput()->getFirstArgument() ?? '',
51
                'command' => $command,
52
                'input' => $this->castInputToString($event->getInput()),
53
                'output' => $this->fetchOutput($event->getOutput()),
54
                'error' => $event->getError()->getMessage(),
55
                'exitCode' => $event->getExitCode(),
56
            ];
57
58
            return;
59
        }
60
61
        if ($event instanceof ConsoleTerminateEvent) {
62
            $this->commands[$event::class] = [
63
                'name' => $command?->getName() ?? $event->getInput()->getFirstArgument() ?? '',
64
                'command' => $command,
65
                'input' => $this->castInputToString($event->getInput()),
66
                'output' => $this->fetchOutput($event->getOutput()),
67
                'exitCode' => $event->getExitCode(),
68
            ];
69
            return;
70
        }
71
72
        $definition = $command?->getDefinition();
73
        $this->commands[$event::class] = [
74
            'name' => $command?->getName() ?? $event->getInput()->getFirstArgument() ?? '',
75
            'command' => $command,
76
            'input' => $this->castInputToString($event->getInput()),
77
            'output' => $this->fetchOutput($event->getOutput()),
78
            'arguments' => $definition?->getArguments() ?? [],
79
            'options' => $definition?->getOptions() ?? [],
80
        ];
81
    }
82
83
    public function getSummary(): array
84
    {
85
        if (empty($this->commands)) {
86
            return [];
87
        }
88
89
        $eventTypes = $this->getSupportedEvents();
90
91
        $commandEvent = null;
92
        foreach ($eventTypes as $eventType) {
93
            if (!array_key_exists($eventType, $this->commands)) {
94
                continue;
95
            }
96
97
            $commandEvent = $this->commands[$eventType];
98
            break;
99
        }
100
101
        if ($commandEvent === null) {
102
            return [];
103
        }
104
105
        return [
106
            'command' => [
107
                'name' => $commandEvent['name'],
108
                'class' => $commandEvent['command'] instanceof Command ? $commandEvent['command']::class : null,
109
                'input' => $commandEvent['input'],
110
                'exitCode' => $commandEvent['exitCode'] ?? self::UNDEFINED_EXIT_CODE,
111
            ],
112
        ];
113
    }
114
115
    private function reset(): void
0 ignored issues
show
Unused Code introduced by
The method reset() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
116
    {
117
        $this->commands = [];
118
    }
119
120
    private function fetchOutput(OutputInterface $output): ?string
121
    {
122
        return $output instanceof ConsoleBufferedOutput ? $output->fetch() : null;
123
    }
124
125
    private function castInputToString(InputInterface $input): ?string
126
    {
127
        return method_exists($input, '__toString') ? $input->__toString() : null;
128
    }
129
130
    private function getSupportedEvents(): array
131
    {
132
        return [
133
            ConsoleErrorEvent::class,
134
            ConsoleTerminateEvent::class,
135
            ConsoleEvent::class,
136
        ];
137
    }
138
}
139