Passed
Push — master ( 3ea542...55f4cf )
by Caen
13:20 queued 13s
created

BuildSiteCommand::handle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 21
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Console\Commands;
6
7
use Hyde\Console\Concerns\Command;
8
use Hyde\Facades\Features;
9
use Hyde\Framework\Features\BuildTasks\PostBuildTasks\GenerateRssFeed;
10
use Hyde\Framework\Features\BuildTasks\PostBuildTasks\GenerateSearch;
11
use Hyde\Framework\Features\BuildTasks\PostBuildTasks\GenerateSitemap;
12
use Hyde\Framework\Services\BuildService;
13
use Hyde\Framework\Services\BuildTaskService;
14
use Hyde\Hyde;
15
use Hyde\Support\BuildWarnings;
16
use Illuminate\Support\Facades\Config;
17
18
/**
19
 * Hyde Command to run the Build Process.
20
 *
21
 * @see \Hyde\Framework\Testing\Feature\StaticSiteServiceTest
22
 */
23
class BuildSiteCommand extends Command
24
{
25
    /** @var string */
26
    protected $signature = 'build 
27
        {--run-dev : Run the NPM dev script after build}
28
        {--run-prod : Run the NPM prod script after build}
29
        {--run-prettier : Format the output using NPM Prettier}
30
        {--pretty-urls : Should links in output use pretty URLs?}
31
        {--no-api : Disable API calls, for example, Torchlight}';
32
33
    /** @var string */
34
    protected $description = 'Build the static site';
35
36
    protected BuildService $service;
37
38
    public function handle(): int
39
    {
40
        $timeStart = microtime(true);
41
42
        $this->title('Building your static site!');
43
44
        $this->service = new BuildService($this->output);
45
46
        $this->runPreBuildActions();
47
48
        $this->service->cleanOutputDirectory();
49
50
        $this->service->transferMediaAssets();
51
52
        $this->service->compileStaticPages();
53
54
        $this->runPostBuildActions();
55
56
        $this->printFinishMessage($timeStart);
0 ignored issues
show
Bug introduced by
It seems like $timeStart can also be of type string; however, parameter $timeStart of Hyde\Console\Commands\Bu...d::printFinishMessage() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

56
        $this->printFinishMessage(/** @scrutinizer ignore-type */ $timeStart);
Loading history...
57
58
        return $this->getExitCode();
59
    }
60
61
    protected function runPreBuildActions(): void
62
    {
63
        if ($this->option('no-api')) {
64
            $this->info('Disabling external API calls');
65
            $this->newLine();
66
            $config = (array) config('hyde.features');
67
            unset($config[array_search('torchlight', $config)]);
68
            Config::set(['hyde.features' => $config]);
69
        }
70
71
        if ($this->option('pretty-urls')) {
72
            $this->info('Generating site with pretty URLs');
73
            $this->newLine();
74
            Config::set(['hyde.pretty_urls' => true]);
75
        }
76
    }
77
78
    public function runPostBuildActions(): void
79
    {
80
        $service = new BuildTaskService($this->output);
81
82
        if ($this->option('run-prettier')) {
83
            $this->runNodeCommand(
84
                'npx prettier '.Hyde::pathToRelative(Hyde::sitePath()).'/**/*.html --write --bracket-same-line',
85
                'Prettifying code!',
86
                'prettify code'
87
            );
88
        }
89
90
        if ($this->option('run-dev')) {
91
            $this->runNodeCommand('npm run dev', 'Building frontend assets for development!');
92
        }
93
94
        if ($this->option('run-prod')) {
95
            $this->runNodeCommand('npm run prod', 'Building frontend assets for production!');
96
        }
97
98
        $service->runIf(GenerateSitemap::class, $this->canGenerateSitemap());
99
        $service->runIf(GenerateRssFeed::class, $this->canGenerateFeed());
100
        $service->runIf(GenerateSearch::class, $this->canGenerateSearch());
101
102
        $service->runPostBuildTasks();
103
    }
104
105
    protected function printFinishMessage(float $timeStart): void
106
    {
107
        if ($this->hasWarnings()) {
108
            $this->newLine();
109
            $this->error('There were some warnings during the build process:');
110
            $this->newLine();
111
            BuildWarnings::writeWarningsToOutput($this->output, $this->output->isVerbose());
112
        }
113
114
        $executionTime = (microtime(true) - $timeStart);
115
        $this->info(sprintf(
116
            "\nAll done! Finished in %s seconds (%sms) with %sMB peak memory usage",
117
            number_format($executionTime, 2),
118
            number_format($executionTime * 1000, 2),
119
            number_format(memory_get_peak_usage() / 1024 / 1024, 2)
120
        ));
121
122
        $this->info('Congratulations! 🎉 Your static site has been built!');
123
        $this->line(
124
            'Your new homepage is stored here -> '.
125
            static::createClickableFilepath(Hyde::sitePath('index.html'))
126
        );
127
    }
128
129
    protected function runNodeCommand(string $command, string $message, ?string $actionMessage = null): void
130
    {
131
        $this->info($message.' This may take a second.');
132
133
        $output = shell_exec(sprintf(
134
            '%s%s',
135
            app()->environment() === 'testing' ? 'echo ' : '',
0 ignored issues
show
introduced by
The method environment() does not exist on Illuminate\Container\Container. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
            app()->/** @scrutinizer ignore-call */ environment() === 'testing' ? 'echo ' : '',
Loading history...
136
            $command
137
        ));
138
139
        $this->line($output ?? sprintf(
140
            '<fg=red>Could not %s! Is NPM installed?</>',
141
            $actionMessage ?? 'run script'
142
        ));
143
    }
144
145
    protected function canGenerateSitemap(): bool
146
    {
147
        return Features::sitemap();
148
    }
149
150
    protected function canGenerateFeed(): bool
151
    {
152
        return Features::rss();
153
    }
154
155
    protected function canGenerateSearch(): bool
156
    {
157
        return Features::hasDocumentationSearch();
158
    }
159
160
    protected function hasWarnings(): bool
161
    {
162
        return BuildWarnings::hasWarnings() && BuildWarnings::reportsWarnings();
163
    }
164
165
    protected function getExitCode(): int
166
    {
167
        if ($this->hasWarnings() && BuildWarnings::reportsWarningsAsExceptions()) {
168
            return self::INVALID;
169
        }
170
171
        return Command::SUCCESS;
172
    }
173
}
174