Passed
Push — master ( 85c0fe...1fafeb )
by Caen
03:50 queued 14s
created

ConsoleOutput::formatLineForOutput()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 6
eloc 7
nc 5
nop 1
dl 0
loc 13
rs 9.2222
c 3
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\RealtimeCompiler;
6
7
use Closure;
8
use Hyde\Hyde;
9
use Illuminate\Support\Str;
10
use Illuminate\Support\Carbon;
11
12
use function max;
13
use function str;
14
use function trim;
15
use function strlen;
16
use function substr;
17
use function sprintf;
18
use function str_repeat;
19
use function str_replace;
20
use function Termwind\render;
21
22
class ConsoleOutput
23
{
24
    protected bool $verbose;
25
26
    public static function printStartMessage(string $host, int $port): void
27
    {
28
        $title = 'HydePHP Realtime Compiler';
29
        $version = ' v'.Hyde::version();
30
31
        $url = sprintf('http://%s:%d', $host, $port);
32
33
        $width = max(strlen("$title $version"), strlen("Listening on $url") + 1) + 1;
34
        $spacing = str_repeat('&nbsp;', $width);
35
        $lines = str_repeat('─', $width);
36
37
        $line1 = '&nbsp;'.sprintf('<span class="text-blue-500">%s</span>&nbsp;<span class="text-gray">%s</span>', $title, $version).str_repeat('&nbsp;', $width - strlen("$title $version"));
38
        $line2 = '&nbsp;'.sprintf('<span class="text-white">Listening on </span>&nbsp;<a href="%s" class="text-yellow-500">%s</a>', $url, $url).str_repeat('&nbsp;', $width - strlen("Listening on $url") - 1);
39
        render(<<<HTML
40
<div class="text-green-500">
41
<br>
42
&nbsp;╭{$lines}╮<br>
43
&nbsp;│{$spacing}│<br>
44
&nbsp;│{$line1}│<br>
45
&nbsp;│{$spacing}│<br>
46
&nbsp;│{$line2}│<br>
47
&nbsp;│{$spacing}│<br>
48
&nbsp;╰{$lines}╯
49
<br>
50
</div>
51
HTML);
52
    }
53
54
    public static function getFormatter(bool $verbose): Closure
55
    {
56
        $console = (new static($verbose));
57
58
        return function (string $type, string $line) use ($console): void {
59
            $console->handleOutput($line);
60
        };
61
    }
62
63
    public function __construct(bool $verbose = false)
64
    {
65
        $this->verbose = $verbose;
66
    }
67
68
    protected function handleOutput(string $buffer): void
69
    {
70
        str($buffer)->trim()->explode("\n")->each(function (string $line): void {
71
            $line = $this->formatLineForOutput($line);
72
73
            if ($line !== null) {
74
                render($line);
75
            }
76
        });
77
    }
78
79
    protected function formatLineForOutput(string $line): ?string
80
    {
81
        if (str_contains($line, 'Development Server (http:')) {
82
            return $this->formatServerStartedLine($line);
83
        }
84
        if (str_contains($line, ']: ')) {
85
            return $this->formatRequestLine($line);
86
        }
87
        if (str_ends_with(trim($line), 'Accepted') || str_ends_with(trim($line), 'Closing')) {
88
            return $this->verbose ? $this->formatRequestStatusLine($line) : null;
89
        }
90
91
        return $this->formatLine($line, Carbon::now());
92
    }
93
94
    protected function formatServerStartedLine(string $line): string
95
    {
96
        return $this->formatLine(sprintf('PHP %s Development Server started. <span class="text-yellow-500">Press Ctrl+C to stop.</span>', PHP_VERSION), $this->parseDate($line), 'green-500');
97
    }
98
99
    protected function formatRequestLine(string $line): string
100
    {
101
        $dateString = Str::betweenFirst($line, '[', ']');
102
        $message = substr($line, strlen($dateString) + 3);
103
104
        $statusCode = Str::between($message, ' [', ']:');
105
        if ($statusCode >= 400) {
106
            $message = str_replace($statusCode, sprintf('<span class="text-red-500">%s</span>', $statusCode), $message);
107
            $iconColor = 'yellow-500';
108
        }
109
110
        return $this->formatLine($message, $this->parseDate($line), $iconColor ?? 'blue-500');
111
    }
112
113
    protected function formatRequestStatusLine(string $line): string
114
    {
115
        $address = trim(Str::between($line, ']', ' '));
116
        $status = str_contains($line, 'Accepted') ? 'Accepted' : 'Closing';
117
118
        return $this->formatLine(sprintf('%s %s', $address, $status), $this->parseDate($line));
119
    }
120
121
    protected function formatLine(string $message, Carbon $date, string $iconColor = 'blue-500'): string
122
    {
123
        return sprintf(<<<'HTML'
124
            <div class="flex w-full justify-between">
125
                <span>
126
                    <span class="text-%s">i</span>
127
                    %s
128
                </span>
129
                <span class="text-gray">%s</span>
130
            </div>
131
            HTML,
132
            $iconColor, $message, $date->format('Y-m-d H:i:s')
133
        );
134
    }
135
136
    protected function parseDate(string $line): Carbon
137
    {
138
        return Carbon::parse(Str::betweenFirst($line, '[', ']'));
139
    }
140
}
141