ScheduleConsoleOutputSubscriber   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 25
eloc 66
c 0
b 0
f 0
dl 0
loc 128
ccs 72
cts 72
cp 1
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getSubscribedEvents() 0 7 1
B beforeSchedule() 0 20 7
A afterTaskMessage() 0 15 4
A __construct() 0 3 1
B afterSchedule() 0 37 7
A afterTask() 0 16 3
A beforeTask() 0 10 2
1
<?php
2
3
namespace Zenstruck\ScheduleBundle\EventListener;
4
5
use Symfony\Component\Console\Style\OutputStyle;
6
use Symfony\Component\Console\Style\SymfonyStyle;
7
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
8
use Zenstruck\ScheduleBundle\Event\AfterScheduleEvent;
9
use Zenstruck\ScheduleBundle\Event\AfterTaskEvent;
10
use Zenstruck\ScheduleBundle\Event\BeforeScheduleEvent;
11
use Zenstruck\ScheduleBundle\Event\BeforeTaskEvent;
12
use Zenstruck\ScheduleBundle\Schedule\Task\Result;
13
14
/**
15
 * @author Kevin Bond <[email protected]>
16
 */
17
final class ScheduleConsoleOutputSubscriber implements EventSubscriberInterface
18
{
19
    /** @var OutputStyle */
20 12
    private $io;
21
22 12
    public function __construct(OutputStyle $io)
23 12
    {
24
        $this->io = $io;
25 12
    }
26
27
    public static function getSubscribedEvents(): array
28 12
    {
29
        return [
30
            BeforeScheduleEvent::class => 'beforeSchedule',
31
            AfterScheduleEvent::class => 'afterSchedule',
32
            BeforeTaskEvent::class => 'beforeTask',
33
            AfterTaskEvent::class => 'afterTask',
34
        ];
35 10
    }
36
37 10
    public function afterSchedule(AfterScheduleEvent $event): void
38
    {
39 10
        $context = $event->runContext();
40 1
41
        if ($context->isSkipped()) {
42 1
            $this->io->note($context->getSkipReason());
43
44
            return;
45 9
        }
46 9
47 9
        $total = \count($context->getResults());
48 9
        $successful = \count($context->getSuccessful());
49 9
        $failures = \count($context->getFailures());
50 9
        $skipped = \count($context->getSkipped());
51
        $run = \count($context->getRun());
52 9
        $messages = ["{$run}/{$total} tasks ran"];
53 1
54
        if (0 === $total) {
55
            return;
56 8
        }
57 8
58
        if ($successful > 0) {
59
            $messages[] = "{$successful} succeeded";
60 8
        }
61 1
62
        if ($skipped > 0) {
63
            $messages[] = "{$skipped} skipped";
64 8
        }
65 4
66
        if ($failures > 0) {
67
            $messages[] = "{$failures} failed";
68 8
        }
69 8
70
        $messages = \implode(', ', $messages).'.';
71 8
        $messages .= " (Duration: {$context->getFormattedDuration()}, Memory: {$context->getFormattedMemory()})";
72 8
73
        $this->io->{$context->isSuccessful() ? 'success' : 'error'}($messages);
74 10
    }
75
76 10
    public function beforeSchedule(BeforeScheduleEvent $event): void
77
    {
78 10
        $context = $event->runContext();
79 10
80
        $allTaskCount = \count($context->getSchedule()->all());
81 10
        $dueTaskCount = \count($context->dueTasks());
82 1
83
        if ($dueTaskCount > 0) {
84 1
            $this->io->{$this->io instanceof SymfonyStyle ? 'comment' : 'text'}(\sprintf(
85
                '%sRunning <info>%s</info> %stask%s. (%s total tasks)',
86
                $context->isForceRun() ? '<error>Force</error> ' : '',
87 9
                $dueTaskCount,
88 9
                $context->isForceRun() ? '' : 'due ',
89 9
                $dueTaskCount > 1 ? 's' : '',
90 9
                $allTaskCount
91 9
            ));
92 9
        }
93 9
94
        if ($this->io->isDebug()) {
95 9
            $this->io->note(\sprintf('No tasks due to run. (%s total tasks)', $allTaskCount));
96
        }
97 8
    }
98
99 8
    public function beforeTask(BeforeTaskEvent $event): void
100 8
    {
101
        $context = $event->runContext();
102 8
        $task = $context->getTask();
103 8
104 8
        $this->io->text(\sprintf(
105 8
            '%s<comment>Running %s:</comment> %s',
106 8
            $context->getScheduleRunContext()->isForceRun() ? '<error>Force</error> ' : '',
107
            $task->getType(),
108 8
            $task->getDescription()
109
        ));
110 8
    }
111
112 8
    public function afterTask(AfterTaskEvent $event): void
113
    {
114 8
        $context = $event->runContext();
115 3
116 3
        if ($this->io->isVerbose() && $output = $context->getResult()->getOutput()) {
117 3
            $this->io->text('---begin output---');
118
            $this->io->write($output);
119
            $this->io->text('---end output---');
120 8
        }
121 8
122 8
        $this->io->text(\sprintf('%s (<comment>Duration:</comment> %s, <comment>Memory:</comment> %s)',
123 8
            $this->afterTaskMessage($context->getResult()),
124
            $context->getFormattedDuration(),
125 8
            $context->getFormattedMemory()
126 8
        ));
127
        $this->io->newLine();
128 8
    }
129
130 8
    private function afterTaskMessage(Result $result): string
131 2
    {
132
        if ($result->isException()) {
133
            return "<error>Exception:</error> {$result->getDescription()}";
134 8
        }
135 2
136
        if ($result->isFailure()) {
137
            return "<error>Failure:</error> {$result->getDescription()}";
138 8
        }
139 1
140
        if ($result->isSkipped()) {
141
            return "<question>Skipped:</question> {$result->getDescription()}";
142 8
        }
143
144
        return '<info>Success.</info>';
145
    }
146
}
147