Passed
Push — master ( 755731...71ac2a )
by Dmitriy
02:36
created

CommandCollector::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 2
rs 10
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(private TimelineCollector $timelineCollector)
29
    {
30
    }
31
32
    public function getCollected(): array
33
    {
34
        return $this->commands;
35
    }
36
37
    public function collect(ConsoleEvent|ConsoleErrorEvent|ConsoleTerminateEvent $event): void
38
    {
39
        if (!$this->isActive()) {
40
            return;
41
        }
42
43
        $this->timelineCollector->collect($this, spl_object_id($event));
44
45
        $command = $event->getCommand();
46
47
        if ($event instanceof ConsoleErrorEvent) {
48
            $this->commands[$event::class] = [
49
                'name' => $event->getInput()->getFirstArgument() ?? '',
50
                'command' => $command,
51
                'input' => $this->castInputToString($event->getInput()),
52
                'output' => $this->fetchOutput($event->getOutput()),
53
                'error' => $event->getError()->getMessage(),
54
                'exitCode' => $event->getExitCode(),
55
            ];
56
57
            return;
58
        }
59
60
        if ($event instanceof ConsoleTerminateEvent) {
61
            $this->commands[$event::class] = [
62
                'name' => $command->getName(),
63
                'command' => $command,
64
                'input' => $this->castInputToString($event->getInput()),
65
                'output' => $this->fetchOutput($event->getOutput()),
66
                'exitCode' => $event->getExitCode(),
67
            ];
68
            return;
69
        }
70
71
        /** @noinspection PhpConditionAlreadyCheckedInspection */
72
        if ($event instanceof ConsoleEvent) {
0 ignored issues
show
introduced by
$event is always a sub-type of Symfony\Component\Console\Event\ConsoleEvent.
Loading history...
73
            $this->commands[$event::class] = [
74
                'name' => $command->getName(),
75
                'command' => $command,
76
                'input' => $this->castInputToString($event->getInput()),
77
                'output' => $this->fetchOutput($event->getOutput()),
78
                'arguments' => $command->getDefinition()->getArguments(),
79
                'options' => $command->getDefinition()->getOptions(),
80
            ];
81
        }
82
    }
83
84
    public function getSummary(): array
85
    {
86
        if (empty($this->commands)) {
87
            return [];
88
        }
89
90
        $eventTypes = $this->getSupportedEvents();
91
92
        $commandEvent = null;
93
        foreach ($eventTypes as $eventType) {
94
            if (!array_key_exists($eventType, $this->commands)) {
95
                continue;
96
            }
97
98
            $commandEvent = $this->commands[$eventType];
99
            break;
100
        }
101
102
        if ($commandEvent === null) {
103
            return [];
104
        }
105
106
        return [
107
            'command' => [
108
                'name' => $commandEvent['name'],
109
                'class' => $commandEvent['command'] instanceof Command ? $commandEvent['command']::class : null,
110
                'input' => $commandEvent['input'],
111
                'exitCode' => $commandEvent['exitCode'] ?? self::UNDEFINED_EXIT_CODE,
112
            ],
113
        ];
114
    }
115
116
    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...
117
    {
118
        $this->commands = [];
119
    }
120
121
    private function fetchOutput(OutputInterface $output): ?string
122
    {
123
        return $output instanceof ConsoleBufferedOutput ? $output->fetch() : null;
124
    }
125
126
    private function castInputToString(InputInterface $input): ?string
127
    {
128
        return method_exists($input, '__toString') ? $input->__toString() : null;
129
    }
130
131
    private function getSupportedEvents(): array
132
    {
133
        return [
134
            ConsoleErrorEvent::class,
135
            ConsoleTerminateEvent::class,
136
            ConsoleEvent::class,
137
        ];
138
    }
139
}
140