Passed
Push — master ( dfdc1d...0594dd )
by Caen
03:44 queued 13s
created

ServeCommand::useBasicOutput()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 1
nc 2
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Console\Commands;
6
7
use Closure;
8
use Hyde\Hyde;
9
use Hyde\Facades\Config;
10
use Illuminate\Support\Arr;
11
use InvalidArgumentException;
12
use Hyde\RealtimeCompiler\ConsoleOutput;
13
use Illuminate\Support\Facades\Process;
14
use LaravelZero\Framework\Commands\Command;
15
use Hyde\Publications\Commands\ValidatingCommand;
16
17
use function sprintf;
18
use function class_exists;
19
20
/**
21
 * Start the realtime compiler server.
22
 *
23
 * @see https://github.com/hydephp/realtime-compiler
24
 */
25
class ServeCommand extends ValidatingCommand
26
{
27
    /** @var string */
28
    protected $signature = 'serve 
29
        {--host= : <comment>[default: "localhost"]</comment>}}
30
        {--port= : <comment>[default: 8080]</comment>}
31
        {--save-preview= : Should the served page be saved to disk? (Overrides config setting)}
32
        {--dashboard= : Enable the realtime compiler dashboard. (Overrides config setting)}
33
        {--pretty-urls= : Enable pretty URLs. (Overrides config setting)}
34
        {--play-cdn= : Enable the Tailwind Play CDN. (Overrides config setting)}
35
    ';
36
37
    /** @var string */
38
    protected $description = 'Start the realtime compiler server.';
39
40
    protected ConsoleOutput $console;
41
42
    public function safeHandle(): int
43
    {
44
        $this->configureOutput();
45
        $this->printStartMessage();
46
47
        $this->runServerProcess(sprintf('php -S %s:%d %s',
48
            $this->getHostSelection(),
49
            $this->getPortSelection(),
50
            $this->getExecutablePath()
51
        ));
52
53
        return Command::SUCCESS;
54
    }
55
56
    protected function getHostSelection(): string
57
    {
58
        return (string) $this->option('host') ?: Config::getString('hyde.server.host', 'localhost');
59
    }
60
61
    protected function getPortSelection(): int
62
    {
63
        return (int) ($this->option('port') ?: Config::getInt('hyde.server.port', 8080));
64
    }
65
66
    protected function getExecutablePath(): string
67
    {
68
        return Hyde::path('vendor/hyde/realtime-compiler/bin/server.php');
69
    }
70
71
    protected function runServerProcess(string $command): void
72
    {
73
        Process::forever()->env($this->getEnvironmentVariables())->run($command, $this->getOutputHandler());
74
    }
75
76
    protected function getEnvironmentVariables(): array
77
    {
78
        return Arr::whereNotNull([
79
            'HYDE_SERVER_REQUEST_OUTPUT' => ! $this->option('no-ansi'),
80
            'HYDE_SERVER_SAVE_PREVIEW' => $this->parseEnvironmentOption('save-preview'),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->parseEnvironmentOption('save-preview') targeting Hyde\Console\Commands\Se...arseEnvironmentOption() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
81
            'HYDE_SERVER_DASHBOARD' => $this->parseEnvironmentOption('dashboard'),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->parseEnvironmentOption('dashboard') targeting Hyde\Console\Commands\Se...arseEnvironmentOption() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
82
            'HYDE_PRETTY_URLS' => $this->parseEnvironmentOption('pretty-urls'),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->parseEnvironmentOption('pretty-urls') targeting Hyde\Console\Commands\Se...arseEnvironmentOption() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
83
            'HYDE_PLAY_CDN' => $this->parseEnvironmentOption('play-cdn'),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->parseEnvironmentOption('play-cdn') targeting Hyde\Console\Commands\Se...arseEnvironmentOption() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
84
        ]);
85
    }
86
87
    protected function configureOutput(): void
88
    {
89
        if (! $this->useBasicOutput()) {
90
            $this->console = new ConsoleOutput($this->output->isVerbose());
91
        }
92
    }
93
94
    protected function printStartMessage(): void
95
    {
96
        $this->useBasicOutput()
97
            ? $this->output->writeln('<info>Starting the HydeRC server...</info> Press Ctrl+C to stop')
98
            : $this->console->printStartMessage($this->getHostSelection(), $this->getPortSelection(), $this->getEnvironmentVariables());
99
    }
100
101
    protected function getOutputHandler(): Closure
102
    {
103
        return $this->useBasicOutput() ? function (string $type, string $line): void {
104
            $this->output->write($line);
105
        } : $this->console->getFormatter();
106
    }
107
108
    protected function useBasicOutput(): bool
109
    {
110
        return $this->option('no-ansi') || ! class_exists(ConsoleOutput::class);
111
    }
112
113
    protected function parseEnvironmentOption(string $name): ?string
114
    {
115
        $value = $this->option($name) ?? $this->checkArgvForOption($name);
116
117
        if ($value !== null) {
118
            return match ($value) {
119
                'true', '' => 'enabled',
120
                'false' => 'disabled',
121
                default => throw new InvalidArgumentException(sprintf('Invalid boolean value for --%s option.', $name))
122
            };
123
        }
124
125
        return null;
126
    }
127
128
    /** Fallback check so that an environment option without a value is acknowledged as true. */
129
    protected function checkArgvForOption(string $name): ?string
130
    {
131
        if (isset($_SERVER['argv'])) {
132
            if (in_array("--$name", $_SERVER['argv'], true)) {
133
                return 'true';
134
            }
135
        }
136
137
        return null;
138
    }
139
}
140